ReactOS  0.4.12-dev-714-gfaac916
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  */
52 static 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 
79  stub = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct ifstub));
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 
137 static struct ifstub *stub_manager_ipid_to_ifstub(struct stub_manager *m, const IPID *ipid)
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;
183  HRESULT hres;
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++;
236  list_add_head(&apt->stubmgrs, &sm->entry);
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 */
260 static void stub_manager_delete(struct stub_manager *m)
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  }
288  __ENDTRY
289 
290  DEBUG_CLEAR_CRITSEC_NAME(&m->lock);
291  DeleteCriticalSection(&m->lock);
292 
293  HeapFree(GetProcessHeap(), 0, m);
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 
316  EnterCriticalSection(&apt->cs);
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 
325  LeaveCriticalSection(&apt->cs);
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;
341  IUnknown *object;
342  HRESULT hres;
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 
350  EnterCriticalSection(&apt->cs);
351  LIST_FOR_EACH( cursor, &apt->stubmgrs )
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 
385  EnterCriticalSection(&apt->cs);
386  LIST_FOR_EACH( cursor, &apt->stubmgrs )
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 */
439 ULONG 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 */
474 static struct stub_manager *get_stub_manager_from_ipid(APARTMENT *apt, const IPID *ipid, struct ifstub **ifstub)
475 {
476  struct stub_manager *result = NULL;
477  struct list *cursor;
478 
479  EnterCriticalSection(&apt->cs);
480  LIST_FOR_EACH( cursor, &apt->stubmgrs )
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 
501 static 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);
512  return RPC_E_INVALID_OBJECT;
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;
519  return RPC_E_INVALID_OBJECT;
520  }
521  return S_OK;
522 }
523 
524 static 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 
546  *stub = ifstub->stubbuffer;
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
557  stub_manager_int_release(stubmgr);
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 */
593 void 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 
628 typedef struct rem_unknown
629 {
632 } RemUnknown;
633 
634 static 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 
660  if (IsEqualIID(riid, &IID_IUnknown) ||
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 
730  stub_manager_int_release(stubmgr);
731  apartment_release(apt);
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 
767  stub_manager_int_release(stubmgr);
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  {
791  hr = E_INVALIDARG;
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 
800  stub_manager_int_release(stubmgr);
802  }
803 
804  return hr;
805 }
806 
807 static 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 MSHLFLAGSP_REMUNKNOWN
static HRESULT RemUnknown_Construct(IRemUnknown **ppRemUnknown)
Definition: stubmanager.c:643
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
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 rem_unknown RemUnknown
#define REFIID
Definition: guiddef.h:113
#define TRUE
Definition: types.h:120
static ULONG WINAPI RemUnknown_Release(IRemUnknown *iface)
Definition: stubmanager.c:686
#define E_NOINTERFACE
Definition: winerror.h:2364
struct stub_manager * get_stub_manager(APARTMENT *apt, OID oid)
Definition: stubmanager.c:380
static void stub_manager_delete(struct stub_manager *m)
Definition: stubmanager.c:260
static HRESULT ipid_to_stub_manager(const IPID *ipid, APARTMENT **stub_apt, struct stub_manager **stub)
Definition: stubmanager.c:524
VOID WINAPI CoTaskMemFree(LPVOID ptr)
Definition: ifs.c:422
HRESULT hr
Definition: shlfolder.c:183
ULONG stub_manager_ext_release(struct stub_manager *m, ULONG refs, BOOL tableweak, BOOL last_unlock_releases)
Definition: stubmanager.c:439
struct list entry
static const IRemUnknownVtbl RemUnknown_Vtbl
Definition: stubmanager.c:634
superblock * sb
Definition: btrfs.c:3876
REFIID riid
Definition: precomp.h:44
#define DEBUG_SET_CRITSEC_NAME(cs, name)
IUnknown * iface
DWORD apartment_release(struct apartment *apt)
Definition: compobj.c:1175
static ULONG WINAPI RemUnknown_AddRef(IRemUnknown *iface)
Definition: stubmanager.c:675
uint8_t entry
Definition: isohybrid.c:63
MSHLFLAGS flags
APARTMENT * apt
__WINE_SERVER_LIST_INLINE void list_add_head(struct list *list, struct list *elem)
Definition: list.h:96
REFIID LPVOID * ppv
Definition: atlbase.h:39
Definition: stubgen.c:11
#define assert(x)
Definition: debug.h:53
IExternalConnection * extern_conn
static HRESULT WINAPI RemUnknown_RemQueryInterface(IRemUnknown *iface, REFIPID ripid, ULONG cRefs, USHORT cIids, IID *iids, REMQIRESULT **ppQIResults)
Definition: stubmanager.c:699
IRemUnknown IRemUnknown_iface
Definition: stubmanager.c:630
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
Definition: features.h:417
const GLfloat * m
Definition: glext.h:10848
HRESULT start_apartment_remote_unknown(APARTMENT *apt)
Definition: stubmanager.c:818
__WINE_SERVER_LIST_INLINE struct list * list_head(const struct list *list)
Definition: list.h:131
CRITICAL_SECTION lock
struct list ifstubs
static struct stub_manager * new_stub_manager(APARTMENT *apt, IUnknown *object)
Definition: stubmanager.c:180
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
struct _stub stub
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
IRpcChannelBuffer * chan
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
long LONG
Definition: pedump.c:60
#define DEBUG_CLEAR_CRITSEC_NAME(cs)
#define FIXME(fmt,...)
Definition: debug.h:110
#define S_FALSE
Definition: winerror.h:2357
#define E_INVALIDARG
Definition: ddrawi.h:101
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:697
#define LIST_FOR_EACH(cursor, list)
Definition: list.h:188
smooth NULL
Definition: ftsmooth.c:416
#define __TRY
Definition: compat.h:70
#define debugstr_guid
Definition: kernel32.h:35
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
DWORD WINAPI GetCurrentThreadId(VOID)
Definition: thread.c:421
BOOL stub_manager_is_table_marshaled(struct stub_manager *m, const IPID *ipid)
Definition: stubmanager.c:609
IRpcStubBuffer * stubbuffer
__WINE_SERVER_LIST_INLINE void list_remove(struct list *elem)
Definition: list.h:108
#define TRACE(s)
Definition: solgame.cpp:4
unsigned int BOOL
Definition: ntddk_ex.h:94
HRESULT hres
Definition: protocol.c:465
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
static HRESULT generate_ipid(struct stub_manager *m, IPID *ipid)
Definition: stubmanager.c:52
OXID_INFO oxid_info
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
LONG HRESULT
Definition: typedefs.h:77
const GUID IID_IUnknown
static RemUnknown * impl_from_IRemUnknown(IRemUnknown *iface)
Definition: stubmanager.c:636
struct list entry
unsigned long DWORD
Definition: ntddk_ex.h:95
static const IID IID_IRemUnknown
Definition: marshal.c:130
#define RPC_E_DISCONNECTED
Definition: winerror.h:2484
HRESULT RPC_CreateServerChannel(DWORD dest_context, void *dest_context_data, IRpcChannelBuffer **chan) DECLSPEC_HIDDEN
Definition: rpc.c:1166
UINT64 OID
Definition: marshal.c:88
GLbitfield flags
Definition: glext.h:7161
APARTMENT * apartment_findfromtid(DWORD tid)
Definition: compobj.c:1303
#define __ENDTRY
Definition: compat.h:72
int ret
static struct ifstub * stub_manager_ipid_to_ifstub(struct stub_manager *m, const IPID *ipid)
Definition: stubmanager.c:137
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:122
BOOL stub_manager_notify_unmarshal(struct stub_manager *m, const IPID *ipid)
Definition: stubmanager.c:562
void RPC_UnregisterInterface(REFIID riid, BOOL wait) DECLSPEC_HIDDEN
Definition: rpc.c:1591
#define InterlockedDecrement
Definition: armddk.h:52
static struct stub_manager * get_stub_manager_from_ipid(APARTMENT *apt, const IPID *ipid, struct ifstub **ifstub)
Definition: stubmanager.c:474
static HRESULT ipid_to_ifstub(const IPID *ipid, APARTMENT **stub_apt, struct stub_manager **stubmgr_ret, struct ifstub **ifstub)
Definition: stubmanager.c:501
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define RPC_E_INVALID_OBJECT
Definition: winerror.h:2496
Definition: _list.h:228
ULONG stub_manager_ext_addref(struct stub_manager *m, ULONG refs, BOOL tableweak)
Definition: stubmanager.c:408
#define WINAPI
Definition: msvc.h:20
#define ERR(fmt,...)
Definition: debug.h:109
struct stub_manager * get_stub_manager_from_object(APARTMENT *apt, IUnknown *obj, BOOL alloc)
Definition: stubmanager.c:337
WINE_DEFAULT_DEBUG_CHANNEL(ole)
APARTMENT * apartment_findfromoxid(OXID oxid, BOOL ref)
Definition: compobj.c:1279
#define S_OK
Definition: intsafe.h:59
static ULONG stub_manager_int_addref(struct stub_manager *This)
Definition: stubmanager.c:297
IUnknown * object
#define InterlockedIncrement
Definition: armddk.h:53
RPC_STATUS WINAPI UuidCreate(UUID *Uuid)
Definition: rpcrt4_main.c:306
static HRESULT WINAPI RemUnknown_RemRelease(IRemUnknown *iface, USHORT cInterfaceRefs, REMINTERFACEREF *InterfaceRefs)
Definition: stubmanager.c:774
const char cursor[]
Definition: icontest.c:13
static void stub_manager_delete_ifstub(struct stub_manager *m, struct ifstub *ifstub)
Definition: stubmanager.c:121
UINT64 OXID
Definition: marshal.c:87
unsigned short USHORT
Definition: pedump.c:61
#define min(a, b)
Definition: monoChain.cc:55
#define alloc
Definition: rosglue.h:13
BOOL WINAPI IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
Definition: compobj.c:4021
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
RPC_STATUS WINAPI UuidCreateNil(UUID *Uuid)
Definition: rpcrt4_main.c:285
struct ifstub * stub_manager_find_ifstub(struct stub_manager *m, REFIID iid, MSHLFLAGS flags)
Definition: stubmanager.c:158
__WINE_SERVER_LIST_INLINE void list_init(struct list *list)
Definition: list.h:149
unsigned int ULONG
Definition: retypes.h:1
static __inline const char * wine_dbgstr_longlong(ULONGLONG ll)
Definition: compat.h:41
struct list stubmgrs
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
#define LIST_ENTRY(type)
Definition: queue.h:175
CRITICAL_SECTION cs
GLuint64EXT * result
Definition: glext.h:11304
void stub_manager_release_marshal_data(struct stub_manager *m, ULONG refs, const IPID *ipid, BOOL tableweak)
Definition: stubmanager.c:593
LPVOID WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: ifs.c:406
#define RPC_C_AUTHN_LEVEL_NONE
Definition: rpcdce.h:146
#define HeapFree(x, y, z)
Definition: compat.h:394
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:90
void * object
Definition: jmemsys.h:48
static HRESULT WINAPI RemUnknown_RemAddRef(IRemUnknown *iface, USHORT cInterfaceRefs, REMINTERFACEREF *InterfaceRefs, HRESULT *pResults)
Definition: stubmanager.c:741
#define __EXCEPT_PAGE_FAULT
Definition: compat.h:71
#define ULONG_MAX
Definition: limits.h:44
DWORD WINAPI GetCurrentProcessId(VOID)
Definition: proc.c:1188
ULONG stub_manager_int_release(struct stub_manager *This)
Definition: stubmanager.c:311
static HRESULT WINAPI RemUnknown_QueryInterface(IRemUnknown *iface, REFIID riid, void **ppv)
Definition: stubmanager.c:656
BOOL remunk_exported