ReactOS 0.4.15-dev-7931-gfd331f1
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 "compobj_private.h"
42
44
45
46/* generates an ipid in the following format (similar to native version):
47 * Data1 = apartment-local ipid counter
48 * Data2 = apartment creator thread ID
49 * Data3 = process ID
50 * Data4 = random value
51 */
52static inline HRESULT generate_ipid(struct stub_manager *m, IPID *ipid)
53{
54 HRESULT hr;
55 hr = UuidCreate(ipid);
56 if (FAILED(hr))
57 {
58 ERR("couldn't create IPID for stub manager %p\n", m);
59 UuidCreateNil(ipid);
60 return hr;
61 }
62
63 ipid->Data1 = InterlockedIncrement(&m->apt->ipidc);
64 ipid->Data2 = (USHORT)m->apt->tid;
65 ipid->Data3 = (USHORT)GetCurrentProcessId();
66 return S_OK;
67}
68
69/* registers a new interface stub COM object with the stub manager and returns registration record */
71 void *dest_context_data, MSHLFLAGS flags)
72{
73 struct ifstub *stub;
74 HRESULT hr;
75
76 TRACE("oid=%s, stubbuffer=%p, iid=%s, dest_context=%x\n", wine_dbgstr_longlong(m->oid), sb,
77 debugstr_guid(iid), dest_context);
78
80 if (!stub) return NULL;
81
82 hr = IUnknown_QueryInterface(m->object, iid, (void **)&stub->iface);
83 if (hr != S_OK)
84 {
86 return NULL;
87 }
88
89 hr = RPC_CreateServerChannel(dest_context, dest_context_data, &stub->chan);
90 if (hr != S_OK)
91 {
92 IUnknown_Release(stub->iface);
94 return NULL;
95 }
96
97 stub->stubbuffer = sb;
98 if (sb) IRpcStubBuffer_AddRef(sb);
99
100 stub->flags = flags;
101 stub->iid = *iid;
102
103 /* FIXME: find a cleaner way of identifying that we are creating an ifstub
104 * for the remunknown interface */
106 stub->ipid = m->oxid_info.ipidRemUnknown;
107 else
108 generate_ipid(m, &stub->ipid);
109
110 EnterCriticalSection(&m->lock);
111 list_add_head(&m->ifstubs, &stub->entry);
112 /* every normal marshal is counted so we don't allow more than we should */
113 if (flags & MSHLFLAGS_NORMAL) m->norm_refs++;
114 LeaveCriticalSection(&m->lock);
115
116 TRACE("ifstub %p created with ipid %s\n", stub, debugstr_guid(&stub->ipid));
117
118 return stub;
119}
120
122{
123 TRACE("m=%p, m->oid=%s, ipid=%s\n", m, wine_dbgstr_longlong(m->oid), debugstr_guid(&ifstub->ipid));
124
126
127 if (!m->disconnected)
129
130 if (ifstub->stubbuffer) IRpcStubBuffer_Release(ifstub->stubbuffer);
131 IUnknown_Release(ifstub->iface);
132 IRpcChannelBuffer_Release(ifstub->chan);
133
135}
136
138{
139 struct list *cursor;
140 struct ifstub *result = NULL;
141
142 EnterCriticalSection(&m->lock);
143 LIST_FOR_EACH( cursor, &m->ifstubs )
144 {
145 struct ifstub *ifstub = LIST_ENTRY( cursor, struct ifstub, entry );
146
147 if (IsEqualGUID(ipid, &ifstub->ipid))
148 {
149 result = ifstub;
150 break;
151 }
152 }
153 LeaveCriticalSection(&m->lock);
154
155 return result;
156}
157
159{
160 struct ifstub *result = NULL;
161 struct ifstub *ifstub;
162
163 EnterCriticalSection(&m->lock);
164 LIST_FOR_EACH_ENTRY( ifstub, &m->ifstubs, struct ifstub, entry )
165 {
166 if (IsEqualIID(iid, &ifstub->iid) && (ifstub->flags == flags))
167 {
168 result = ifstub;
169 break;
170 }
171 }
172 LeaveCriticalSection(&m->lock);
173
174 return result;
175}
176
177/* creates a new stub manager and adds it into the apartment. caller must
178 * release stub manager when it is no longer required. the apartment and
179 * external refs together take one implicit ref */
181{
182 struct stub_manager *sm;
184
185 assert( apt );
186
187 sm = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct stub_manager));
188 if (!sm) return NULL;
189
190 list_init(&sm->ifstubs);
191
193 DEBUG_SET_CRITSEC_NAME(&sm->lock, "stub_manager");
194
195 IUnknown_AddRef(object);
196 sm->object = object;
197 sm->apt = apt;
198
199 /* start off with 2 references because the stub is in the apartment
200 * and the caller will also hold a reference */
201 sm->refs = 2;
202 sm->weakrefs = 0;
203
204 sm->oxid_info.dwPid = GetCurrentProcessId();
205 sm->oxid_info.dwTid = GetCurrentThreadId();
206 /*
207 * FIXME: this is a hack for marshalling IRemUnknown. In real
208 * DCOM, the IPID of the IRemUnknown interface is generated like
209 * any other and passed to the OXID resolver which then returns it
210 * when queried. We don't have an OXID resolver yet so instead we
211 * use a magic IPID reserved for IRemUnknown.
212 */
213 sm->oxid_info.ipidRemUnknown.Data1 = 0xffffffff;
214 sm->oxid_info.ipidRemUnknown.Data2 = 0xffff;
215 sm->oxid_info.ipidRemUnknown.Data3 = 0xffff;
216 assert(sizeof(sm->oxid_info.ipidRemUnknown.Data4) == sizeof(apt->oxid));
217 memcpy(sm->oxid_info.ipidRemUnknown.Data4, &apt->oxid, sizeof(OXID));
218 sm->oxid_info.dwAuthnHint = RPC_C_AUTHN_LEVEL_NONE;
219 sm->oxid_info.psa = NULL /* FIXME */;
220
221 /* Yes, that's right, this starts at zero. that's zero EXTERNAL
222 * refs, i.e., nobody has unmarshalled anything yet. We can't have
223 * negative refs because the stub manager cannot be explicitly
224 * killed, it has to die by somebody unmarshalling then releasing
225 * the marshalled ifptr.
226 */
227 sm->extrefs = 0;
228 sm->disconnected = FALSE;
229
230 hres = IUnknown_QueryInterface(object, &IID_IExternalConnection, (void**)&sm->extern_conn);
231 if(FAILED(hres))
232 sm->extern_conn = NULL;
233
235 sm->oid = apt->oidc++;
238
239 TRACE("Created new stub manager (oid=%s) at %p for object with IUnknown %p\n", wine_dbgstr_longlong(sm->oid), sm, object);
240
241 return sm;
242}
243
245{
246 struct ifstub *ifstub;
247
248 EnterCriticalSection(&m->lock);
249 if (!m->disconnected)
250 {
251 LIST_FOR_EACH_ENTRY(ifstub, &m->ifstubs, struct ifstub, entry)
253
254 m->disconnected = TRUE;
255 }
256 LeaveCriticalSection(&m->lock);
257}
258
259/* caller must remove stub manager from apartment prior to calling this function */
261{
262 struct list *cursor;
263
264 TRACE("destroying %p (oid=%s)\n", m, wine_dbgstr_longlong(m->oid));
265
266 /* release every ifstub */
267 while ((cursor = list_head(&m->ifstubs)))
268 {
269 struct ifstub *ifstub = LIST_ENTRY(cursor, struct ifstub, entry);
271 }
272
273 if(m->extern_conn)
274 IExternalConnection_Release(m->extern_conn);
275
276 CoTaskMemFree(m->oxid_info.psa);
277
278 /* Some broken apps crash in object destructors. We have a test showing
279 * that on winxp+ those crashes are caught and ignored. */
280 __TRY
281 {
282 IUnknown_Release(m->object);
283 }
285 {
286 ERR("Got page fault when releasing stub!\n");
287 }
289
291 DeleteCriticalSection(&m->lock);
292
294}
295
296/* increments the internal refcount */
298{
299 ULONG refs;
300
301 EnterCriticalSection(&This->apt->cs);
302 refs = ++This->refs;
303 LeaveCriticalSection(&This->apt->cs);
304
305 TRACE("before %d\n", refs - 1);
306
307 return refs;
308}
309
310/* decrements the internal refcount */
312{
313 ULONG refs;
314 APARTMENT *apt = This->apt;
315
317 refs = --This->refs;
318
319 TRACE("after %d\n", refs);
320
321 /* remove from apartment so no other thread can access it... */
322 if (!refs)
323 list_remove(&This->entry);
324
326
327 /* ... so now we can delete it without being inside the apartment critsec */
328 if (!refs)
330
331 return refs;
332}
333
334/* gets the stub manager associated with an object - caller must have
335 * a reference to the apartment while a reference to the stub manager is held.
336 * it must also call release on the stub manager when it is no longer needed */
338{
339 struct stub_manager *result = NULL;
340 struct list *cursor;
343
344 hres = IUnknown_QueryInterface(obj, &IID_IUnknown, (void**)&object);
345 if (FAILED(hres)) {
346 ERR("QueryInterface(IID_IUnknown failed): %08x\n", hres);
347 return NULL;
348 }
349
352 {
353 struct stub_manager *m = LIST_ENTRY( cursor, struct stub_manager, entry );
354
355 if (m->object == object)
356 {
357 result = m;
359 break;
360 }
361 }
363
364 if (result) {
365 TRACE("found %p for object %p\n", result, object);
366 }else if (alloc) {
367 TRACE("not found, creating new stub manager...\n");
368 result = new_stub_manager(apt, object);
369 }else {
370 TRACE("not found for object %p\n", object);
371 }
372
373 IUnknown_Release(object);
374 return result;
375}
376
377/* gets the stub manager associated with an object id - caller must have
378 * a reference to the apartment while a reference to the stub manager is held.
379 * it must also call release on the stub manager when it is no longer needed */
381{
382 struct stub_manager *result = NULL;
383 struct list *cursor;
384
387 {
388 struct stub_manager *m = LIST_ENTRY( cursor, struct stub_manager, entry );
389
390 if (m->oid == oid)
391 {
392 result = m;
394 break;
395 }
396 }
398
399 if (result)
400 TRACE("found %p for oid %s\n", result, wine_dbgstr_longlong(oid));
401 else
402 TRACE("not found for oid %s\n", wine_dbgstr_longlong(oid));
403
404 return result;
405}
406
407/* add some external references (ie from a client that unmarshaled an ifptr) */
409{
410 BOOL first_extern_ref;
411 ULONG rc;
412
413 EnterCriticalSection(&m->lock);
414
415 first_extern_ref = refs && !m->extrefs;
416
417 /* make sure we don't overflow extrefs */
418 refs = min(refs, (ULONG_MAX-1 - m->extrefs));
419 rc = (m->extrefs += refs);
420
421 if (tableweak)
422 rc += ++m->weakrefs;
423
424 LeaveCriticalSection(&m->lock);
425
426 TRACE("added %u refs to %p (oid %s), rc is now %u\n", refs, m, wine_dbgstr_longlong(m->oid), rc);
427
428 /*
429 * NOTE: According to tests, creating a stub causes two AddConnection calls followed by
430 * one ReleaseConnection call (with fLastReleaseCloses=FALSE).
431 */
432 if(first_extern_ref && m->extern_conn)
433 IExternalConnection_AddConnection(m->extern_conn, EXTCONN_STRONG, 0);
434
435 return rc;
436}
437
438/* remove some external references */
439ULONG stub_manager_ext_release(struct stub_manager *m, ULONG refs, BOOL tableweak, BOOL last_unlock_releases)
440{
441 BOOL last_extern_ref;
442 ULONG rc;
443
444 EnterCriticalSection(&m->lock);
445
446 /* make sure we don't underflow extrefs */
447 refs = min(refs, m->extrefs);
448 rc = (m->extrefs -= refs);
449
450 if (tableweak)
451 --m->weakrefs;
452 if (!last_unlock_releases)
453 rc += m->weakrefs;
454
455 last_extern_ref = refs && !m->extrefs;
456
457 LeaveCriticalSection(&m->lock);
458
459 TRACE("removed %u refs from %p (oid %s), rc is now %u\n", refs, m, wine_dbgstr_longlong(m->oid), rc);
460
461 if (last_extern_ref && m->extern_conn)
462 IExternalConnection_ReleaseConnection(m->extern_conn, EXTCONN_STRONG, 0, last_unlock_releases);
463
464 if (rc == 0)
465 if (!(m->extern_conn && last_unlock_releases && m->weakrefs))
467
468 return rc;
469}
470
471/* gets the stub manager associated with an ipid - caller must have
472 * a reference to the apartment while a reference to the stub manager is held.
473 * it must also call release on the stub manager when it is no longer needed */
475{
476 struct stub_manager *result = NULL;
477 struct list *cursor;
478
481 {
482 struct stub_manager *m = LIST_ENTRY( cursor, struct stub_manager, entry );
483
484 if ((*ifstub = stub_manager_ipid_to_ifstub(m, ipid)))
485 {
486 result = m;
488 break;
489 }
490 }
492
493 if (result)
494 TRACE("found %p for ipid %s\n", result, debugstr_guid(ipid));
495 else
496 ERR("not found for ipid %s\n", debugstr_guid(ipid));
497
498 return result;
499}
500
501static HRESULT ipid_to_ifstub(const IPID *ipid, APARTMENT **stub_apt,
502 struct stub_manager **stubmgr_ret, struct ifstub **ifstub)
503{
504 /* FIXME: hack for IRemUnknown */
505 if (ipid->Data2 == 0xffff)
506 *stub_apt = apartment_findfromoxid(*(const OXID *)ipid->Data4, TRUE);
507 else
508 *stub_apt = apartment_findfromtid(ipid->Data2);
509 if (!*stub_apt)
510 {
511 TRACE("Couldn't find apartment corresponding to TID 0x%04x\n", ipid->Data2);
513 }
514 *stubmgr_ret = get_stub_manager_from_ipid(*stub_apt, ipid, ifstub);
515 if (!*stubmgr_ret)
516 {
517 apartment_release(*stub_apt);
518 *stub_apt = NULL;
520 }
521 return S_OK;
522}
523
524static HRESULT ipid_to_stub_manager(const IPID *ipid, APARTMENT **stub_apt, struct stub_manager **stub)
525{
526 struct ifstub *ifstub;
527 return ipid_to_ifstub(ipid, stub_apt, stub, &ifstub);
528}
529
530/* gets the apartment, stub and channel of an object. the caller must
531 * release the references to all objects (except iface) if the function
532 * returned success, otherwise no references are returned. */
534 struct stub_manager **manager,
536 IID *iid, IUnknown **iface)
537{
538 struct stub_manager *stubmgr;
539 struct ifstub *ifstub;
540 APARTMENT *apt;
541 HRESULT hr;
542
543 hr = ipid_to_ifstub(ipid, &apt, &stubmgr, &ifstub);
544 if (hr != S_OK) return RPC_E_DISCONNECTED;
545
547 IRpcStubBuffer_AddRef(*stub);
548 *chan = ifstub->chan;
549 IRpcChannelBuffer_AddRef(*chan);
550 *stub_apt = apt;
551 *iid = ifstub->iid;
552 *iface = ifstub->iface;
553
554 if (manager)
555 *manager = stubmgr;
556 else
558 return S_OK;
559}
560
561/* returns TRUE if it is possible to unmarshal, FALSE otherwise. */
563{
564 BOOL ret = TRUE;
565 struct ifstub *ifstub;
566
568 {
569 ERR("attempted unmarshal of unknown IPID %s\n", debugstr_guid(ipid));
570 return FALSE;
571 }
572
573 EnterCriticalSection(&m->lock);
574
575 /* track normal marshals so we can enforce rules whilst in-process */
576 if (ifstub->flags & MSHLFLAGS_NORMAL)
577 {
578 if (m->norm_refs)
579 m->norm_refs--;
580 else
581 {
582 ERR("attempted invalid normal unmarshal, norm_refs is zero\n");
583 ret = FALSE;
584 }
585 }
586
587 LeaveCriticalSection(&m->lock);
588
589 return ret;
590}
591
592/* handles refcounting for CoReleaseMarshalData */
593void stub_manager_release_marshal_data(struct stub_manager *m, ULONG refs, const IPID *ipid, BOOL tableweak)
594{
595 struct ifstub *ifstub;
596
598 return;
599
600 if (ifstub->flags & MSHLFLAGS_TABLEWEAK)
601 refs = 0;
602 else if (ifstub->flags & MSHLFLAGS_TABLESTRONG)
603 refs = 1;
604
605 stub_manager_ext_release(m, refs, tableweak, !tableweak);
606}
607
608/* is an ifstub table marshaled? */
610{
612
613 assert( ifstub );
614
615 return ifstub->flags & (MSHLFLAGS_TABLESTRONG | MSHLFLAGS_TABLEWEAK);
616}
617
618
619/*****************************************************************************
620 *
621 * IRemUnknown implementation
622 *
623 *
624 * Note: this object is not related to the lifetime of a stub_manager, but it
625 * interacts with stub managers.
626 */
627
628typedef struct rem_unknown
629{
633
634static const IRemUnknownVtbl RemUnknown_Vtbl;
635
637{
638 return CONTAINING_RECORD(iface, RemUnknown, IRemUnknown_iface);
639}
640
641
642/* construct an IRemUnknown object with one outstanding reference */
644{
645 RemUnknown *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
646
647 if (!This) return E_OUTOFMEMORY;
648
649 This->IRemUnknown_iface.lpVtbl = &RemUnknown_Vtbl;
650 This->refs = 1;
651
652 *ppRemUnknown = &This->IRemUnknown_iface;
653 return S_OK;
654}
655
657{
658 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
659
662 {
663 *ppv = iface;
664 IRemUnknown_AddRef(iface);
665 return S_OK;
666 }
667
668 if (!IsEqualIID(riid, &IID_IExternalConnection))
669 FIXME("No interface for iid %s\n", debugstr_guid(riid));
670
671 *ppv = NULL;
672 return E_NOINTERFACE;
673}
674
676{
677 ULONG refs;
679
680 refs = InterlockedIncrement(&This->refs);
681
682 TRACE("%p before: %d\n", iface, refs-1);
683 return refs;
684}
685
687{
688 ULONG refs;
690
691 refs = InterlockedDecrement(&This->refs);
692 if (!refs)
694
695 TRACE("%p after: %d\n", iface, refs);
696 return refs;
697}
698
700 REFIPID ripid, ULONG cRefs, USHORT cIids, IID *iids /* [size_is(cIids)] */,
701 REMQIRESULT **ppQIResults /* [size_is(,cIids)] */)
702{
703 HRESULT hr;
704 USHORT i;
705 USHORT successful_qis = 0;
706 APARTMENT *apt;
707 struct stub_manager *stubmgr;
708 struct ifstub *ifstub;
709 DWORD dest_context;
710 void *dest_context_data;
711
712 TRACE("(%p)->(%s, %d, %d, %p, %p)\n", iface, debugstr_guid(ripid), cRefs, cIids, iids, ppQIResults);
713
714 hr = ipid_to_ifstub(ripid, &apt, &stubmgr, &ifstub);
715 if (hr != S_OK) return hr;
716
717 IRpcChannelBuffer_GetDestCtx(ifstub->chan, &dest_context, &dest_context_data);
718
719 *ppQIResults = CoTaskMemAlloc(sizeof(REMQIRESULT) * cIids);
720
721 for (i = 0; i < cIids; i++)
722 {
723 HRESULT hrobj = marshal_object(apt, &(*ppQIResults)[i].std, &iids[i],
724 stubmgr->object, dest_context, dest_context_data, MSHLFLAGS_NORMAL);
725 if (hrobj == S_OK)
726 successful_qis++;
727 (*ppQIResults)[i].hResult = hrobj;
728 }
729
732
733 if (successful_qis == cIids)
734 return S_OK; /* we got all requested interfaces */
735 else if (successful_qis == 0)
736 return E_NOINTERFACE; /* we didn't get any interfaces */
737 else
738 return S_FALSE; /* we got some interfaces */
739}
740
742 USHORT cInterfaceRefs,
743 REMINTERFACEREF* InterfaceRefs /* [size_is(cInterfaceRefs)] */,
744 HRESULT *pResults /* [size_is(cInterfaceRefs)] */)
745{
746 HRESULT hr = S_OK;
747 USHORT i;
748
749 TRACE("(%p)->(%d, %p, %p)\n", iface, cInterfaceRefs, InterfaceRefs, pResults);
750
751 for (i = 0; i < cInterfaceRefs; i++)
752 {
753 APARTMENT *apt;
754 struct stub_manager *stubmgr;
755
756 pResults[i] = ipid_to_stub_manager(&InterfaceRefs[i].ipid, &apt, &stubmgr);
757 if (pResults[i] != S_OK)
758 {
759 hr = S_FALSE;
760 continue;
761 }
762
763 stub_manager_ext_addref(stubmgr, InterfaceRefs[i].cPublicRefs, FALSE);
764 if (InterfaceRefs[i].cPrivateRefs)
765 FIXME("Adding %d refs securely not implemented\n", InterfaceRefs[i].cPrivateRefs);
766
769 }
770
771 return hr;
772}
773
775 USHORT cInterfaceRefs,
776 REMINTERFACEREF* InterfaceRefs /* [size_is(cInterfaceRefs)] */)
777{
778 HRESULT hr = S_OK;
779 USHORT i;
780
781 TRACE("(%p)->(%d, %p)\n", iface, cInterfaceRefs, InterfaceRefs);
782
783 for (i = 0; i < cInterfaceRefs; i++)
784 {
785 APARTMENT *apt;
786 struct stub_manager *stubmgr;
787
788 hr = ipid_to_stub_manager(&InterfaceRefs[i].ipid, &apt, &stubmgr);
789 if (hr != S_OK)
790 {
792 /* FIXME: we should undo any changes already made in this function */
793 break;
794 }
795
796 stub_manager_ext_release(stubmgr, InterfaceRefs[i].cPublicRefs, FALSE, TRUE);
797 if (InterfaceRefs[i].cPrivateRefs)
798 FIXME("Releasing %d refs securely not implemented\n", InterfaceRefs[i].cPrivateRefs);
799
802 }
803
804 return hr;
805}
806
807static const IRemUnknownVtbl RemUnknown_Vtbl =
808{
815};
816
817/* starts the IRemUnknown listener for the current apartment */
819{
820 IRemUnknown *pRemUnknown;
821 HRESULT hr = S_OK;
822
824 if (!apt->remunk_exported)
825 {
826 /* create the IRemUnknown object */
827 hr = RemUnknown_Construct(&pRemUnknown);
828 if (hr == S_OK)
829 {
830 STDOBJREF stdobjref; /* dummy - not used */
831 /* register it with the stub manager */
832 hr = marshal_object(apt, &stdobjref, &IID_IRemUnknown, (IUnknown *)pRemUnknown, MSHCTX_DIFFERENTMACHINE, NULL, MSHLFLAGS_NORMAL|MSHLFLAGSP_REMUNKNOWN);
833 /* release our reference to the object as the stub manager will manage the life cycle for us */
834 IRemUnknown_Release(pRemUnknown);
835 if (hr == S_OK)
837 }
838 }
840 return hr;
841}
#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
const GUID IID_IUnknown
#define FIXME(fmt,...)
Definition: debug.h:111
#define ERR(fmt,...)
Definition: debug.h:110
Definition: list.h:37
HRESULT RPC_CreateServerChannel(DWORD dest_context, void *dest_context_data, IRpcChannelBuffer **chan) DECLSPEC_HIDDEN
Definition: rpc.c:1162
#define MSHLFLAGSP_REMUNKNOWN
#define DEBUG_SET_CRITSEC_NAME(cs, name)
#define DEBUG_CLEAR_CRITSEC_NAME(cs)
void RPC_UnregisterInterface(REFIID riid, BOOL wait) DECLSPEC_HIDDEN
Definition: rpc.c:1587
HRESULT marshal_object(APARTMENT *apt, STDOBJREF *stdobjref, REFIID riid, IUnknown *obj, DWORD dest_context, void *dest_context_data, MSHLFLAGS mshlflags) DECLSPEC_HIDDEN
Definition: marshal.c:121
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
#define __TRY
Definition: compat.h:80
static __inline const char * wine_dbgstr_longlong(ULONGLONG ll)
Definition: compat.h:49
#define HeapFree(x, y, z)
Definition: compat.h:735
#define __ENDTRY
Definition: compat.h:82
#define __EXCEPT_PAGE_FAULT
Definition: compat.h:81
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
DWORD apartment_release(struct apartment *apt)
Definition: compobj.c:1172
APARTMENT * apartment_findfromoxid(OXID oxid, BOOL ref)
Definition: compobj.c:1276
APARTMENT * apartment_findfromtid(DWORD tid)
Definition: compobj.c:1300
#define assert(x)
Definition: debug.h:53
superblock * sb
Definition: btrfs.c:4261
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
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
VOID WINAPI CoTaskMemFree(LPVOID ptr)
Definition: ifs.c:442
LPVOID WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: ifs.c:426
#define ULONG_MAX
Definition: limits.h:44
REFIID riid
Definition: atlbase.h:39
REFIID LPVOID * ppv
Definition: atlbase.h:39
#define S_OK
Definition: intsafe.h:52
#define FAILED(hr)
Definition: intsafe.h:51
uint32_t entry
Definition: isohybrid.c:63
#define debugstr_guid
Definition: kernel32.h:35
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
HRESULT hres
Definition: protocol.c:465
UINT64 OID
Definition: marshal.c:88
static const IID IID_IRemUnknown
Definition: marshal.c:130
UINT64 OXID
Definition: marshal.c:87
#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 RPC_C_AUTHN_LEVEL_NONE
Definition: rpcdce.h:146
RPC_STATUS WINAPI UuidCreateNil(UUID *Uuid)
Definition: rpcrt4_main.c:284
RPC_STATUS WINAPI UuidCreate(UUID *Uuid)
Definition: rpcrt4_main.c:305
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
#define LIST_FOR_EACH(cursor, list)
Definition: list.h:188
HRESULT hr
Definition: shlfolder.c:183
#define TRACE(s)
Definition: solgame.cpp:4
Definition: stubgen.c:11
CRITICAL_SECTION cs
BOOL remunk_exported
struct list stubmgrs
struct list entry
IUnknown * iface
IRpcStubBuffer * stubbuffer
MSHLFLAGS flags
IRpcChannelBuffer * chan
Definition: list.h:15
IRemUnknown IRemUnknown_iface
Definition: stubmanager.c:630
CRITICAL_SECTION lock
OXID_INFO oxid_info
IExternalConnection * extern_conn
IUnknown * object
struct list ifstubs
APARTMENT * apt
struct list entry
struct _stub stub
static const IRemUnknownVtbl RemUnknown_Vtbl
Definition: stubmanager.c:634
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:70
struct stub_manager * get_stub_manager(APARTMENT *apt, OID oid)
Definition: stubmanager.c:380
static void stub_manager_delete_ifstub(struct stub_manager *m, struct ifstub *ifstub)
Definition: stubmanager.c:121
ULONG stub_manager_ext_release(struct stub_manager *m, ULONG refs, BOOL tableweak, BOOL last_unlock_releases)
Definition: stubmanager.c:439
ULONG stub_manager_int_release(struct stub_manager *This)
Definition: stubmanager.c:311
static ULONG stub_manager_int_addref(struct stub_manager *This)
Definition: stubmanager.c:297
static struct stub_manager * get_stub_manager_from_ipid(APARTMENT *apt, const IPID *ipid, struct ifstub **ifstub)
Definition: stubmanager.c:474
static HRESULT WINAPI RemUnknown_QueryInterface(IRemUnknown *iface, REFIID riid, void **ppv)
Definition: stubmanager.c:656
BOOL stub_manager_is_table_marshaled(struct stub_manager *m, const IPID *ipid)
Definition: stubmanager.c:609
static void stub_manager_delete(struct stub_manager *m)
Definition: stubmanager.c:260
struct stub_manager * get_stub_manager_from_object(APARTMENT *apt, IUnknown *obj, BOOL alloc)
Definition: stubmanager.c:337
static HRESULT WINAPI RemUnknown_RemQueryInterface(IRemUnknown *iface, REFIPID ripid, ULONG cRefs, USHORT cIids, IID *iids, REMQIRESULT **ppQIResults)
Definition: stubmanager.c:699
static HRESULT generate_ipid(struct stub_manager *m, IPID *ipid)
Definition: stubmanager.c:52
static struct ifstub * stub_manager_ipid_to_ifstub(struct stub_manager *m, const IPID *ipid)
Definition: stubmanager.c:137
static HRESULT ipid_to_stub_manager(const IPID *ipid, APARTMENT **stub_apt, struct stub_manager **stub)
Definition: stubmanager.c:524
HRESULT ipid_get_dispatch_params(const IPID *ipid, APARTMENT **stub_apt, struct stub_manager **manager, IRpcStubBuffer **stub, IRpcChannelBuffer **chan, IID *iid, IUnknown **iface)
Definition: stubmanager.c:533
void stub_manager_disconnect(struct stub_manager *m)
Definition: stubmanager.c:244
BOOL stub_manager_notify_unmarshal(struct stub_manager *m, const IPID *ipid)
Definition: stubmanager.c:562
static ULONG WINAPI RemUnknown_AddRef(IRemUnknown *iface)
Definition: stubmanager.c:675
static HRESULT WINAPI RemUnknown_RemRelease(IRemUnknown *iface, USHORT cInterfaceRefs, REMINTERFACEREF *InterfaceRefs)
Definition: stubmanager.c:774
HRESULT start_apartment_remote_unknown(APARTMENT *apt)
Definition: stubmanager.c:818
struct ifstub * stub_manager_find_ifstub(struct stub_manager *m, REFIID iid, MSHLFLAGS flags)
Definition: stubmanager.c:158
struct rem_unknown RemUnknown
void stub_manager_release_marshal_data(struct stub_manager *m, ULONG refs, const IPID *ipid, BOOL tableweak)
Definition: stubmanager.c:593
static struct stub_manager * new_stub_manager(APARTMENT *apt, IUnknown *object)
Definition: stubmanager.c:180
static HRESULT RemUnknown_Construct(IRemUnknown **ppRemUnknown)
Definition: stubmanager.c:643
static RemUnknown * impl_from_IRemUnknown(IRemUnknown *iface)
Definition: stubmanager.c:636
ULONG stub_manager_ext_addref(struct stub_manager *m, ULONG refs, BOOL tableweak)
Definition: stubmanager.c:408
static HRESULT ipid_to_ifstub(const IPID *ipid, APARTMENT **stub_apt, struct stub_manager **stubmgr_ret, struct ifstub **ifstub)
Definition: stubmanager.c:501
static ULONG WINAPI RemUnknown_Release(IRemUnknown *iface)
Definition: stubmanager.c:686
static HRESULT WINAPI RemUnknown_RemAddRef(IRemUnknown *iface, USHORT cInterfaceRefs, REMINTERFACEREF *InterfaceRefs, HRESULT *pResults)
Definition: stubmanager.c:741
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:751
#define LIST_ENTRY(type)
Definition: queue.h:175
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
int ret
DWORD WINAPI GetCurrentThreadId(void)
Definition: thread.c:459
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
DWORD WINAPI GetCurrentProcessId(void)
Definition: proc.c:1158
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
#define WINAPI
Definition: msvc.h:6
#define S_FALSE
Definition: winerror.h:2357
#define RPC_E_INVALID_OBJECT
Definition: winerror.h:2496
#define E_NOINTERFACE
Definition: winerror.h:2364
#define RPC_E_DISCONNECTED
Definition: winerror.h:2484