ReactOS 0.4.16-dev-2332-g4cba65d
stubmanager.c
Go to the documentation of this file.
1/*
2 * A stub manager is an object that controls interface stubs. It is
3 * identified by an OID (object identifier) and acts as the network
4 * identity of the object. There can be many stub managers in a
5 * process or apartment.
6 *
7 * Copyright 2002 Marcus Meissner
8 * Copyright 2004 Mike Hearn for CodeWeavers
9 * Copyright 2004 Robert Shearman (for CodeWeavers)
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26#define COBJMACROS
27
28#include <assert.h>
29#include <stdarg.h>
30#include <limits.h>
31
32#include "windef.h"
33#include "winbase.h"
34#include "winuser.h"
35#include "objbase.h"
36#include "rpc.h"
37
38#include "wine/debug.h"
39#include "wine/exception.h"
40
41#include "initguid.h"
42#include "dcom.h"
43#include "combase_private.h"
44
46
47/* generates an ipid in the following format (similar to native version):
48 * Data1 = apartment-local ipid counter
49 * Data2 = apartment creator thread ID, or 0 for an MTA.
50 * Data3 = process ID
51 * Data4 = random value
52 */
53static inline HRESULT generate_ipid(struct stub_manager *m, IPID *ipid)
54{
55 HRESULT hr;
56 hr = UuidCreate(ipid);
57 if (FAILED(hr))
58 {
59 ERR("couldn't create IPID for stub manager %p\n", m);
60 UuidCreateNil(ipid);
61 return hr;
62 }
63
64 ipid->Data1 = InterlockedIncrement(&m->apt->ipidc);
65 ipid->Data2 = !m->apt->multi_threaded ? (USHORT)m->apt->tid : 0;
66 ipid->Data3 = (USHORT)GetCurrentProcessId();
67 return S_OK;
68}
69
70/* registers a new interface stub COM object with the stub manager and returns registration record */
72 void *dest_context_data, MSHLFLAGS flags)
73{
74 struct ifstub *stub;
75 HRESULT hr;
76
77 TRACE("oid=%s, stubbuffer=%p, iid=%s, dest_context=%lx\n", wine_dbgstr_longlong(m->oid), sb,
78 debugstr_guid(iid), dest_context);
79
80 stub = calloc(1, sizeof(struct ifstub));
81 if (!stub) return NULL;
82
83 hr = IUnknown_QueryInterface(m->object, iid, (void **)&stub->iface);
84 if (hr != S_OK)
85 {
86 free(stub);
87 return NULL;
88 }
89
90 hr = rpc_create_serverchannel(dest_context, dest_context_data, &stub->chan);
91 if (hr != S_OK)
92 {
93 IUnknown_Release(stub->iface);
94 free(stub);
95 return NULL;
96 }
97
98 stub->stubbuffer = sb;
99 if (sb) IRpcStubBuffer_AddRef(sb);
100
101 stub->flags = flags;
102 stub->iid = *iid;
103
104 /* FIXME: find a cleaner way of identifying that we are creating an ifstub
105 * for the remunknown interface */
107 stub->ipid = m->oxid_info.ipidRemUnknown;
108 else
109 generate_ipid(m, &stub->ipid);
110
111 EnterCriticalSection(&m->lock);
112 list_add_head(&m->ifstubs, &stub->entry);
113 /* every normal marshal is counted so we don't allow more than we should */
114 if (flags & MSHLFLAGS_NORMAL) m->norm_refs++;
115 LeaveCriticalSection(&m->lock);
116
117 TRACE("ifstub %p created with ipid %s\n", stub, debugstr_guid(&stub->ipid));
118
119 return stub;
120}
121
123{
124 TRACE("m=%p, m->oid=%s, ipid=%s\n", m, wine_dbgstr_longlong(m->oid), debugstr_guid(&ifstub->ipid));
125
127
128 if (!m->disconnected)
130
131 if (ifstub->stubbuffer) IRpcStubBuffer_Release(ifstub->stubbuffer);
132 IUnknown_Release(ifstub->iface);
133 IRpcChannelBuffer_Release(ifstub->chan);
134
135 free(ifstub);
136}
137
139{
140 struct ifstub *result = NULL, *ifstub;
141
142 EnterCriticalSection(&m->lock);
143 LIST_FOR_EACH_ENTRY(ifstub, &m->ifstubs, struct ifstub, entry)
144 {
145 if (IsEqualGUID(ipid, &ifstub->ipid))
146 {
147 result = ifstub;
148 break;
149 }
150 }
151 LeaveCriticalSection(&m->lock);
152
153 return result;
154}
155
157{
158 struct ifstub *result = NULL;
159 struct ifstub *ifstub;
160
161 EnterCriticalSection(&m->lock);
162 LIST_FOR_EACH_ENTRY( ifstub, &m->ifstubs, struct ifstub, entry )
163 {
164 if (IsEqualIID(iid, &ifstub->iid) && (ifstub->flags == flags))
165 {
166 result = ifstub;
167 break;
168 }
169 }
170 LeaveCriticalSection(&m->lock);
171
172 return result;
173}
174
175/* creates a new stub manager and adds it into the apartment. caller must
176 * release stub manager when it is no longer required. the apartment and
177 * external refs together take one implicit ref */
178static struct stub_manager *new_stub_manager(struct apartment *apt, IUnknown *object)
179{
180 struct stub_manager *sm;
182
183 assert(apt);
184
185 sm = calloc(1, sizeof(struct stub_manager));
186 if (!sm) return NULL;
187
188 list_init(&sm->ifstubs);
189
191 sm->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": stub_manager");
192
193 IUnknown_AddRef(object);
194 sm->object = object;
195 sm->apt = apt;
196
197 /* start off with 2 references because the stub is in the apartment
198 * and the caller will also hold a reference */
199 sm->refs = 2;
200 sm->weakrefs = 0;
201
202 sm->oxid_info.dwPid = GetCurrentProcessId();
203 sm->oxid_info.dwTid = GetCurrentThreadId();
204 /*
205 * FIXME: this is a hack for marshalling IRemUnknown. In real
206 * DCOM, the IPID of the IRemUnknown interface is generated like
207 * any other and passed to the OXID resolver which then returns it
208 * when queried. We don't have an OXID resolver yet so instead we
209 * use a magic IPID reserved for IRemUnknown.
210 */
211 sm->oxid_info.ipidRemUnknown.Data1 = 0xffffffff;
212 sm->oxid_info.ipidRemUnknown.Data2 = 0xffff;
213 sm->oxid_info.ipidRemUnknown.Data3 = 0xffff;
214 assert(sizeof(sm->oxid_info.ipidRemUnknown.Data4) == sizeof(apt->oxid));
215 memcpy(sm->oxid_info.ipidRemUnknown.Data4, &apt->oxid, sizeof(OXID));
216 sm->oxid_info.dwAuthnHint = RPC_C_AUTHN_LEVEL_NONE;
217 sm->oxid_info.psa = NULL /* FIXME */;
218
219 /* Yes, that's right, this starts at zero. that's zero EXTERNAL
220 * refs, i.e., nobody has unmarshalled anything yet. We can't have
221 * negative refs because the stub manager cannot be explicitly
222 * killed, it has to die by somebody unmarshalling then releasing
223 * the marshalled ifptr.
224 */
225 sm->extrefs = 0;
226 sm->disconnected = FALSE;
227
228 hres = IUnknown_QueryInterface(object, &IID_IExternalConnection, (void**)&sm->extern_conn);
229 if(FAILED(hres))
230 sm->extern_conn = NULL;
231
233 sm->oid = apt->oidc++;
234 list_add_head(&apt->stubmgrs, &sm->entry);
236
237 TRACE("Created new stub manager (oid=%s) at %p for object with IUnknown %p\n", wine_dbgstr_longlong(sm->oid), sm, object);
238
239 return sm;
240}
241
243{
244 struct ifstub *ifstub;
245
246 EnterCriticalSection(&m->lock);
247 if (!m->disconnected)
248 {
249 LIST_FOR_EACH_ENTRY(ifstub, &m->ifstubs, struct ifstub, entry)
251
252 m->disconnected = TRUE;
253 }
254 LeaveCriticalSection(&m->lock);
255}
256
257/* caller must remove stub manager from apartment prior to calling this function */
259{
260 struct list *cursor;
261
262 TRACE("destroying %p (oid=%s)\n", m, wine_dbgstr_longlong(m->oid));
263
264 /* release every ifstub */
265 while ((cursor = list_head(&m->ifstubs)))
266 {
267 struct ifstub *ifstub = LIST_ENTRY(cursor, struct ifstub, entry);
269 }
270
271 if(m->extern_conn)
272 IExternalConnection_Release(m->extern_conn);
273
274 CoTaskMemFree(m->oxid_info.psa);
275
276 /* Some broken apps crash in object destructors. We have a test showing
277 * that on winxp+ those crashes are caught and ignored. */
278 __TRY
279 {
280 IUnknown_Release(m->object);
281 }
283 {
284 ERR("Got page fault when releasing stub!\n");
285 }
287
288 m->lock.DebugInfo->Spare[0] = 0;
289 DeleteCriticalSection(&m->lock);
290
291 free(m);
292}
293
294/* increments the internal refcount */
296{
297 ULONG refs;
298
299 EnterCriticalSection(&m->apt->cs);
300 refs = ++m->refs;
301 LeaveCriticalSection(&m->apt->cs);
302
303 TRACE("before %ld\n", refs - 1);
304
305 return refs;
306}
307
308/* decrements the internal refcount */
310{
311 ULONG refs;
312 struct apartment *apt = m->apt;
313
315 refs = --m->refs;
316
317 TRACE("after %ld\n", refs);
318
319 /* remove from apartment so no other thread can access it... */
320 if (!refs)
321 list_remove(&m->entry);
322
324
325 /* ... so now we can delete it without being inside the apartment critsec */
326 if (!refs)
328
329 return refs;
330}
331
332/* gets the stub manager associated with an object - caller must have
333 * a reference to the apartment while a reference to the stub manager is held.
334 * it must also call release on the stub manager when it is no longer needed */
336{
337 struct stub_manager *result = NULL, *m;
340
341 hres = IUnknown_QueryInterface(obj, &IID_IUnknown, (void**)&object);
342 if (FAILED(hres))
343 {
344 ERR("QueryInterface(IID_IUnknown failed): %#lx\n", hres);
345 return NULL;
346 }
347
349 LIST_FOR_EACH_ENTRY(m, &apt->stubmgrs, struct stub_manager, entry)
350 {
351 if (m->object == object)
352 {
353 result = m;
355 break;
356 }
357 }
359
360 if (result)
361 {
362 TRACE("found %p for object %p\n", result, object);
363 }
364 else if (alloc)
365 {
366 TRACE("not found, creating new stub manager...\n");
367 result = new_stub_manager(apt, object);
368 }
369 else
370 {
371 TRACE("not found for object %p\n", object);
372 }
373
374 IUnknown_Release(object);
375 return result;
376}
377
378/* gets the stub manager associated with an object id - caller must have
379 * a reference to the apartment while a reference to the stub manager is held.
380 * it must also call release on the stub manager when it is no longer needed */
382{
383 struct stub_manager *result = NULL, *m;
384
386 LIST_FOR_EACH_ENTRY(m, &apt->stubmgrs, struct stub_manager, entry)
387 {
388 if (m->oid == oid)
389 {
390 result = m;
392 break;
393 }
394 }
396
397 if (result)
398 TRACE("found %p for oid %s\n", result, wine_dbgstr_longlong(oid));
399 else
400 TRACE("not found for oid %s\n", wine_dbgstr_longlong(oid));
401
402 return result;
403}
404
405/* add some external references (ie from a client that unmarshaled an ifptr) */
407{
408 BOOL first_extern_ref;
409 ULONG rc;
410
411 EnterCriticalSection(&m->lock);
412
413 first_extern_ref = refs && !m->extrefs;
414
415 /* make sure we don't overflow extrefs */
416 refs = min(refs, (ULONG_MAX-1 - m->extrefs));
417 rc = (m->extrefs += refs);
418
419 if (tableweak)
420 rc += ++m->weakrefs;
421
422 LeaveCriticalSection(&m->lock);
423
424 TRACE("added %lu refs to %p (oid %s), rc is now %lu\n", refs, m, wine_dbgstr_longlong(m->oid), rc);
425
426 /*
427 * NOTE: According to tests, creating a stub causes two AddConnection calls followed by
428 * one ReleaseConnection call (with fLastReleaseCloses=FALSE).
429 */
430 if(first_extern_ref && m->extern_conn)
431 IExternalConnection_AddConnection(m->extern_conn, EXTCONN_STRONG, 0);
432
433 return rc;
434}
435
436/* remove some external references */
437ULONG stub_manager_ext_release(struct stub_manager *m, ULONG refs, BOOL tableweak, BOOL last_unlock_releases)
438{
439 BOOL last_extern_ref;
440 ULONG rc;
441
442 EnterCriticalSection(&m->lock);
443
444 /* make sure we don't underflow extrefs */
445 refs = min(refs, m->extrefs);
446 rc = (m->extrefs -= refs);
447
448 if (tableweak)
449 --m->weakrefs;
450 if (!last_unlock_releases)
451 rc += m->weakrefs;
452
453 last_extern_ref = refs && !m->extrefs;
454
455 LeaveCriticalSection(&m->lock);
456
457 TRACE("removed %lu refs from %p (oid %s), rc is now %lu\n", refs, m, wine_dbgstr_longlong(m->oid), rc);
458
459 if (last_extern_ref && m->extern_conn)
460 IExternalConnection_ReleaseConnection(m->extern_conn, EXTCONN_STRONG, 0, last_unlock_releases);
461
462 if (rc == 0)
463 if (!(m->extern_conn && last_unlock_releases && m->weakrefs))
465
466 return rc;
467}
468
469/* gets the stub manager associated with an ipid - caller must have
470 * a reference to the apartment while a reference to the stub manager is held.
471 * it must also call release on the stub manager when it is no longer needed */
472static struct stub_manager *get_stub_manager_from_ipid(struct apartment *apt, const IPID *ipid, struct ifstub **ifstub)
473{
474 struct stub_manager *result = NULL, *m;
475
477 LIST_FOR_EACH_ENTRY(m, &apt->stubmgrs, struct stub_manager, entry)
478 {
479 if ((*ifstub = stub_manager_ipid_to_ifstub(m, ipid)))
480 {
481 result = m;
483 break;
484 }
485 }
487
488 if (result)
489 TRACE("found %p for ipid %s\n", result, debugstr_guid(ipid));
490 else
491 ERR("not found for ipid %s\n", debugstr_guid(ipid));
492
493 return result;
494}
495
496static HRESULT ipid_to_ifstub(const IPID *ipid, struct apartment **stub_apt,
497 struct stub_manager **stubmgr_ret, struct ifstub **ifstub)
498{
499 /* FIXME: hack for IRemUnknown */
500 if (ipid->Data2 == 0xffff)
501 *stub_apt = apartment_findfromoxid(*(const OXID *)ipid->Data4);
502 else if (!ipid->Data2 && (ipid->Data3 == (USHORT)GetCurrentProcessId()))
503 *stub_apt = apartment_get_mta();
504 else
505 *stub_apt = apartment_findfromtid(ipid->Data2);
506 if (!*stub_apt)
507 {
508 TRACE("Couldn't find apartment corresponding to TID 0x%04x, PID 0x%04x\n", ipid->Data2, ipid->Data3);
510 }
511 *stubmgr_ret = get_stub_manager_from_ipid(*stub_apt, ipid, ifstub);
512 if (!*stubmgr_ret)
513 {
514 apartment_release(*stub_apt);
515 *stub_apt = NULL;
517 }
518 return S_OK;
519}
520
521static HRESULT ipid_to_stub_manager(const IPID *ipid, struct apartment **stub_apt, struct stub_manager **stub)
522{
523 struct ifstub *ifstub;
524 return ipid_to_ifstub(ipid, stub_apt, stub, &ifstub);
525}
526
527/* gets the apartment, stub and channel of an object. the caller must
528 * release the references to all objects (except iface) if the function
529 * returned success, otherwise no references are returned. */
532 IID *iid, IUnknown **iface)
533{
534 struct stub_manager *stubmgr;
535 struct ifstub *ifstub;
536 struct apartment *apt;
537 HRESULT hr;
538
539 hr = ipid_to_ifstub(ipid, &apt, &stubmgr, &ifstub);
540 if (hr != S_OK) return RPC_E_DISCONNECTED;
541
543 IRpcStubBuffer_AddRef(*stub);
544 *chan = ifstub->chan;
545 IRpcChannelBuffer_AddRef(*chan);
546 *stub_apt = apt;
547 *iid = ifstub->iid;
548 *iface = ifstub->iface;
549
550 if (manager)
551 *manager = stubmgr;
552 else
554 return S_OK;
555}
556
557HRESULT ipid_get_dest_context(const IPID *ipid, MSHCTX *dest_context, void **dest_context_data)
558{
559 struct stub_manager *stubmgr;
560 struct ifstub *ifstub;
561 struct apartment *apt;
562 void *data;
563 HRESULT hr;
564 DWORD ctx;
565
566 hr = ipid_to_ifstub(ipid, &apt, &stubmgr, &ifstub);
567 if (hr != S_OK) return RPC_E_DISCONNECTED;
568
569 hr = IRpcChannelBuffer_GetDestCtx(ifstub->chan, &ctx, &data);
570 if (SUCCEEDED(hr))
571 {
572 *dest_context = ctx;
573 *dest_context_data = data;
574 }
575
578
579 return hr;
580}
581
582/* returns TRUE if it is possible to unmarshal, FALSE otherwise. */
584{
585 BOOL ret = TRUE;
586 struct ifstub *ifstub;
587
589 {
590 ERR("attempted unmarshal of unknown IPID %s\n", debugstr_guid(ipid));
591 return FALSE;
592 }
593
594 EnterCriticalSection(&m->lock);
595
596 /* track normal marshals so we can enforce rules whilst in-process */
597 if (ifstub->flags & MSHLFLAGS_NORMAL)
598 {
599 if (m->norm_refs)
600 m->norm_refs--;
601 else
602 {
603 ERR("attempted invalid normal unmarshal, norm_refs is zero\n");
604 ret = FALSE;
605 }
606 }
607
608 LeaveCriticalSection(&m->lock);
609
610 return ret;
611}
612
613/* handles refcounting for CoReleaseMarshalData */
614void stub_manager_release_marshal_data(struct stub_manager *m, ULONG refs, const IPID *ipid, BOOL tableweak)
615{
616 struct ifstub *ifstub;
617
619 return;
620
621 if (ifstub->flags & MSHLFLAGS_TABLEWEAK)
622 refs = 0;
623 else if (ifstub->flags & MSHLFLAGS_TABLESTRONG)
624 refs = 1;
625
626 stub_manager_ext_release(m, refs, tableweak, !tableweak);
627}
628
629/* is an ifstub table marshaled? */
631{
633
634 assert(ifstub);
635
636 return ifstub->flags & (MSHLFLAGS_TABLESTRONG | MSHLFLAGS_TABLEWEAK);
637}
638
639/*****************************************************************************
640 *
641 * IRemUnknown implementation
642 *
643 *
644 * Note: this object is not related to the lifetime of a stub_manager, but it
645 * interacts with stub managers.
646 */
647
648typedef struct rem_unknown
649{
653
654static const IRemUnknownVtbl RemUnknown_Vtbl;
655
657{
658 return CONTAINING_RECORD(iface, RemUnknown, IRemUnknown_iface);
659}
660
661/* construct an IRemUnknown object with one outstanding reference */
663{
664 RemUnknown *object = malloc(sizeof(*object));
665
666 if (!object)
667 return E_OUTOFMEMORY;
668
669 object->IRemUnknown_iface.lpVtbl = &RemUnknown_Vtbl;
670 object->refs = 1;
671
672 *ppRemUnknown = &object->IRemUnknown_iface;
673 return S_OK;
674}
675
677{
678 TRACE("%p, %s, %p\n", iface, debugstr_guid(riid), ppv);
679
682 {
683 *ppv = iface;
684 IRemUnknown_AddRef(iface);
685 return S_OK;
686 }
687
688 if (!IsEqualIID(riid, &IID_IExternalConnection))
689 FIXME("No interface for iid %s\n", debugstr_guid(riid));
690
691 *ppv = NULL;
692 return E_NOINTERFACE;
693}
694
696{
697 ULONG refs;
698 RemUnknown *remunk = impl_from_IRemUnknown(iface);
699
700 refs = InterlockedIncrement(&remunk->refs);
701
702 TRACE("%p before: %ld\n", iface, refs-1);
703 return refs;
704}
705
707{
708 ULONG refs;
709 RemUnknown *remunk = impl_from_IRemUnknown(iface);
710
711 refs = InterlockedDecrement(&remunk->refs);
712 if (!refs)
713 free(remunk);
714
715 TRACE("%p after: %ld\n", iface, refs);
716 return refs;
717}
718
720 REFIPID ripid, ULONG cRefs, USHORT cIids, IID *iids /* [size_is(cIids)] */,
721 REMQIRESULT **ppQIResults /* [size_is(,cIids)] */)
722{
723 HRESULT hr;
724 USHORT i;
725 USHORT successful_qis = 0;
726 struct apartment *apt;
727 struct stub_manager *stubmgr;
728 struct ifstub *ifstub;
729 DWORD dest_context;
730 void *dest_context_data;
731
732 TRACE("%p, %s, %ld, %d, %p, %p.\n", iface, debugstr_guid(ripid), cRefs, cIids, iids, ppQIResults);
733
734 hr = ipid_to_ifstub(ripid, &apt, &stubmgr, &ifstub);
735 if (hr != S_OK) return hr;
736
737 IRpcChannelBuffer_GetDestCtx(ifstub->chan, &dest_context, &dest_context_data);
738
739 *ppQIResults = CoTaskMemAlloc(sizeof(REMQIRESULT) * cIids);
740
741 for (i = 0; i < cIids; i++)
742 {
743 HRESULT hrobj = marshal_object(apt, &(*ppQIResults)[i].std, &iids[i],
744 stubmgr->object, dest_context, dest_context_data, MSHLFLAGS_NORMAL);
745 if (hrobj == S_OK)
746 successful_qis++;
747 (*ppQIResults)[i].hResult = hrobj;
748 }
749
752
753 if (successful_qis == cIids)
754 return S_OK; /* we got all requested interfaces */
755 else if (successful_qis == 0)
756 return E_NOINTERFACE; /* we didn't get any interfaces */
757 else
758 return S_FALSE; /* we got some interfaces */
759}
760
762 USHORT cInterfaceRefs,
763 REMINTERFACEREF* InterfaceRefs /* [size_is(cInterfaceRefs)] */,
764 HRESULT *pResults /* [size_is(cInterfaceRefs)] */)
765{
766 HRESULT hr = S_OK;
767 USHORT i;
768
769 TRACE("%p, %d, %p, %p\n", iface, cInterfaceRefs, InterfaceRefs, pResults);
770
771 for (i = 0; i < cInterfaceRefs; i++)
772 {
773 struct apartment *apt;
774 struct stub_manager *stubmgr;
775
776 pResults[i] = ipid_to_stub_manager(&InterfaceRefs[i].ipid, &apt, &stubmgr);
777 if (pResults[i] != S_OK)
778 {
779 hr = S_FALSE;
780 continue;
781 }
782
783 stub_manager_ext_addref(stubmgr, InterfaceRefs[i].cPublicRefs, FALSE);
784 if (InterfaceRefs[i].cPrivateRefs)
785 FIXME("Adding %ld refs securely not implemented\n", InterfaceRefs[i].cPrivateRefs);
786
789 }
790
791 return hr;
792}
793
795 USHORT cInterfaceRefs,
796 REMINTERFACEREF* InterfaceRefs /* [size_is(cInterfaceRefs)] */)
797{
798 HRESULT hr = S_OK;
799 USHORT i;
800
801 TRACE("%p, %d, %p\n", iface, cInterfaceRefs, InterfaceRefs);
802
803 for (i = 0; i < cInterfaceRefs; i++)
804 {
805 struct apartment *apt;
806 struct stub_manager *stubmgr;
807
808 hr = ipid_to_stub_manager(&InterfaceRefs[i].ipid, &apt, &stubmgr);
809 if (hr != S_OK)
810 {
812 /* FIXME: we should undo any changes already made in this function */
813 break;
814 }
815
816 stub_manager_ext_release(stubmgr, InterfaceRefs[i].cPublicRefs, FALSE, TRUE);
817 if (InterfaceRefs[i].cPrivateRefs)
818 FIXME("Releasing %ld refs securely not implemented\n", InterfaceRefs[i].cPrivateRefs);
819
822 }
823
824 return hr;
825}
826
827static const IRemUnknownVtbl RemUnknown_Vtbl =
828{
835};
836
837/* starts the IRemUnknown listener for the current apartment */
839{
840 IRemUnknown *pRemUnknown;
841 HRESULT hr = S_OK;
842
844 if (!apt->remunk_exported)
845 {
846 /* create the IRemUnknown object */
847 hr = RemUnknown_Construct(&pRemUnknown);
848 if (hr == S_OK)
849 {
850 STDOBJREF stdobjref; /* dummy - not used */
851 /* register it with the stub manager */
852 hr = marshal_object(apt, &stdobjref, &IID_IRemUnknown, (IUnknown *)pRemUnknown,
853 MSHCTX_DIFFERENTMACHINE, NULL, MSHLFLAGS_NORMAL|MSHLFLAGSP_REMUNKNOWN);
854 /* release our reference to the object as the stub manager will manage the life cycle for us */
855 IRemUnknown_Release(pRemUnknown);
856 if (hr == S_OK)
857 apt->remunk_exported = TRUE;
858 }
859 }
861 return hr;
862}
struct apartment * apartment_get_mta(void)
Definition: apartment.c:607
void apartment_release(struct apartment *apt)
Definition: apartment.c:444
struct apartment * apartment_findfromtid(DWORD tid)
Definition: apartment.c:657
struct apartment * apartment_findfromoxid(OXID oxid)
Definition: apartment.c:635
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
static void list_remove(struct list_entry *entry)
Definition: list.h:90
static void list_add_head(struct list_entry *head, struct list_entry *entry)
Definition: list.h:76
static void list_init(struct list_entry *head)
Definition: list.h:51
#define FIXME(fmt,...)
Definition: precomp.h:53
#define ERR(fmt,...)
Definition: precomp.h:57
const GUID IID_IUnknown
Definition: list.h:37
#define MSHLFLAGSP_REMUNKNOWN
void rpc_unregister_interface(REFIID riid, BOOL wait)
Definition: rpc.c:2143
HRESULT marshal_object(struct apartment *apt, STDOBJREF *stdobjref, REFIID riid, IUnknown *object, DWORD dest_context, void *dest_context_data, MSHLFLAGS mshlflags)
Definition: marshal.c:870
HRESULT rpc_create_serverchannel(DWORD dest_context, void *dest_context_data, IRpcChannelBuffer **chan)
Definition: rpc.c:1709
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define __TRY
Definition: compat.h:80
static __inline const char * wine_dbgstr_longlong(ULONGLONG ll)
Definition: compat.h:49
#define __ENDTRY
Definition: compat.h:82
#define __EXCEPT_PAGE_FAULT
Definition: compat.h:81
BOOL WINAPI InitializeCriticalSectionEx(OUT LPCRITICAL_SECTION lpCriticalSection, IN DWORD dwSpinCount, IN DWORD flags)
Definition: sync.c:107
#define assert(_expr)
Definition: assert.h:32
#define ULONG_MAX
Definition: limits.h:31
return ret
Definition: mutex.c:146
superblock * sb
Definition: btrfs.c:4261
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLbitfield flags
Definition: glext.h:7161
GLuint64EXT * result
Definition: glext.h:11304
const GLfloat * m
Definition: glext.h:10848
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
const char cursor[]
Definition: icontest.c:13
REFIID riid
Definition: atlbase.h:39
REFIID LPVOID * ppv
Definition: atlbase.h:39
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
uint32_t entry
Definition: isohybrid.c:63
#define debugstr_guid
Definition: kernel32.h:35
void *WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: malloc.c:381
void WINAPI CoTaskMemFree(void *ptr)
Definition: malloc.c:389
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
HRESULT hres
Definition: protocol.c:465
UINT64 OID
Definition: marshal.c:87
static const IID IID_IRemUnknown
Definition: marshal.c:129
UINT64 OXID
Definition: marshal.c:86
#define min(a, b)
Definition: monoChain.cc:55
Definition: features.h:417
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
#define REFIID
Definition: guiddef.h:118
#define alloc
Definition: rosglue.h:13
#define calloc
Definition: rosglue.h:14
#define RPC_C_AUTHN_LEVEL_NONE
Definition: rpcdce.h:146
RPC_STATUS WINAPI UuidCreateNil(UUID *Uuid)
Definition: rpcrt4_main.c:309
RPC_STATUS WINAPI UuidCreate(UUID *Uuid)
Definition: rpcrt4_main.c:330
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
HRESULT hr
Definition: shlfolder.c:183
#define TRACE(s)
Definition: solgame.cpp:4
PRTL_CRITICAL_SECTION_DEBUG DebugInfo
Definition: rtltypes.h:1450
Definition: stubgen.c:11
CRITICAL_SECTION cs
struct list entry
IUnknown * iface
IRpcStubBuffer * stubbuffer
MSHLFLAGS flags
IRpcChannelBuffer * chan
Definition: list.h:15
IRemUnknown IRemUnknown_iface
Definition: stubmanager.c:650
CRITICAL_SECTION lock
OXID_INFO oxid_info
IExternalConnection * extern_conn
struct apartment * apt
IUnknown * object
struct list ifstubs
struct list entry
struct _stub stub
static const IRemUnknownVtbl RemUnknown_Vtbl
Definition: stubmanager.c:654
struct ifstub * stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *sb, REFIID iid, DWORD dest_context, void *dest_context_data, MSHLFLAGS flags)
Definition: stubmanager.c:71
HRESULT ipid_get_dispatch_params(const IPID *ipid, struct apartment **stub_apt, struct stub_manager **manager, IRpcStubBuffer **stub, IRpcChannelBuffer **chan, IID *iid, IUnknown **iface)
Definition: stubmanager.c:530
static void stub_manager_delete_ifstub(struct stub_manager *m, struct ifstub *ifstub)
Definition: stubmanager.c:122
ULONG stub_manager_ext_release(struct stub_manager *m, ULONG refs, BOOL tableweak, BOOL last_unlock_releases)
Definition: stubmanager.c:437
static HRESULT WINAPI RemUnknown_QueryInterface(IRemUnknown *iface, REFIID riid, void **ppv)
Definition: stubmanager.c:676
static struct stub_manager * new_stub_manager(struct apartment *apt, IUnknown *object)
Definition: stubmanager.c:178
BOOL stub_manager_is_table_marshaled(struct stub_manager *m, const IPID *ipid)
Definition: stubmanager.c:630
static void stub_manager_delete(struct stub_manager *m)
Definition: stubmanager.c:258
ULONG stub_manager_int_release(struct stub_manager *m)
Definition: stubmanager.c:309
static HRESULT WINAPI RemUnknown_RemQueryInterface(IRemUnknown *iface, REFIPID ripid, ULONG cRefs, USHORT cIids, IID *iids, REMQIRESULT **ppQIResults)
Definition: stubmanager.c:719
static HRESULT generate_ipid(struct stub_manager *m, IPID *ipid)
Definition: stubmanager.c:53
static struct ifstub * stub_manager_ipid_to_ifstub(struct stub_manager *m, const IPID *ipid)
Definition: stubmanager.c:138
static HRESULT ipid_to_ifstub(const IPID *ipid, struct apartment **stub_apt, struct stub_manager **stubmgr_ret, struct ifstub **ifstub)
Definition: stubmanager.c:496
static ULONG stub_manager_int_addref(struct stub_manager *m)
Definition: stubmanager.c:295
struct stub_manager * get_stub_manager(struct apartment *apt, OID oid)
Definition: stubmanager.c:381
struct stub_manager * get_stub_manager_from_object(struct apartment *apt, IUnknown *obj, BOOL alloc)
Definition: stubmanager.c:335
HRESULT ipid_get_dest_context(const IPID *ipid, MSHCTX *dest_context, void **dest_context_data)
Definition: stubmanager.c:557
void stub_manager_disconnect(struct stub_manager *m)
Definition: stubmanager.c:242
BOOL stub_manager_notify_unmarshal(struct stub_manager *m, const IPID *ipid)
Definition: stubmanager.c:583
static ULONG WINAPI RemUnknown_AddRef(IRemUnknown *iface)
Definition: stubmanager.c:695
static HRESULT WINAPI RemUnknown_RemRelease(IRemUnknown *iface, USHORT cInterfaceRefs, REMINTERFACEREF *InterfaceRefs)
Definition: stubmanager.c:794
static struct stub_manager * get_stub_manager_from_ipid(struct apartment *apt, const IPID *ipid, struct ifstub **ifstub)
Definition: stubmanager.c:472
struct ifstub * stub_manager_find_ifstub(struct stub_manager *m, REFIID iid, MSHLFLAGS flags)
Definition: stubmanager.c:156
struct rem_unknown RemUnknown
void stub_manager_release_marshal_data(struct stub_manager *m, ULONG refs, const IPID *ipid, BOOL tableweak)
Definition: stubmanager.c:614
HRESULT start_apartment_remote_unknown(struct apartment *apt)
Definition: stubmanager.c:838
static HRESULT RemUnknown_Construct(IRemUnknown **ppRemUnknown)
Definition: stubmanager.c:662
static RemUnknown * impl_from_IRemUnknown(IRemUnknown *iface)
Definition: stubmanager.c:656
ULONG stub_manager_ext_addref(struct stub_manager *m, ULONG refs, BOOL tableweak)
Definition: stubmanager.c:406
static HRESULT ipid_to_stub_manager(const IPID *ipid, struct apartment **stub_apt, struct stub_manager **stub)
Definition: stubmanager.c:521
static ULONG WINAPI RemUnknown_Release(IRemUnknown *iface)
Definition: stubmanager.c:706
static HRESULT WINAPI RemUnknown_RemAddRef(IRemUnknown *iface, USHORT cInterfaceRefs, REMINTERFACEREF *InterfaceRefs, HRESULT *pResults)
Definition: stubmanager.c:761
#define LIST_ENTRY(type)
Definition: queue.h:175
#define DWORD_PTR
Definition: treelist.c:76
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
DWORD WINAPI GetCurrentThreadId(void)
Definition: thread.c:459
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
DWORD WINAPI GetCurrentProcessId(void)
Definition: proc.c:1156
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
#define WINAPI
Definition: msvc.h:6
#define S_FALSE
Definition: winerror.h:3451
#define RPC_E_INVALID_OBJECT
Definition: winerror.h:3568
#define E_NOINTERFACE
Definition: winerror.h:3479
#define RPC_E_DISCONNECTED
Definition: winerror.h:3556
#define RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO
Definition: winnt_old.h:1156