ReactOS  0.4.13-dev-101-g0ca4b50
marshal.c
Go to the documentation of this file.
1 /*
2  * Marshalling library
3  *
4  * Copyright 2002 Marcus Meissner
5  * Copyright 2004 Mike Hearn, for CodeWeavers
6  * Copyright 2004 Rob Shearman, for CodeWeavers
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22 
23 #include <stdarg.h>
24 #include <string.h>
25 #include <assert.h>
26 
27 #define COBJMACROS
28 
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winuser.h"
32 #include "objbase.h"
33 #include "ole2.h"
34 #include "winerror.h"
35 #include "wine/unicode.h"
36 
37 #include "compobj_private.h"
38 
39 #include "wine/debug.h"
40 
42 
43 /* number of refs given out for normal marshaling */
44 #define NORMALEXTREFS 5
45 
46 
47 /* private flag indicating that the object was marshaled as table-weak */
48 #define SORFP_TABLEWEAK SORF_OXRES1
49 /* private flag indicating that the caller does not want to notify the stub
50  * when the proxy disconnects or is destroyed */
51 #define SORFP_NOLIFETIMEMGMT SORF_OXRES2
52 
53 /* imported object / proxy manager */
55 {
59  struct apartment *parent; /* owning apartment (RO) */
60  struct list entry; /* entry in apartment (CS parent->cs) */
61  OXID oxid; /* object exported ID (RO) */
62  OXID_INFO oxid_info; /* string binding, ipid of rem unknown and other information (RO) */
63  OID oid; /* object ID (RO) */
64  struct list interfaces; /* imported interfaces (CS cs) */
65  LONG refs; /* proxy reference count (LOCK) */
66  CRITICAL_SECTION cs; /* thread safety for this object and children */
67  ULONG sorflags; /* STDOBJREF flags (RO) */
68  IRemUnknown *remunk; /* proxy to IRemUnknown used for lifecycle management (CS cs) */
69  HANDLE remoting_mutex; /* mutex used for synchronizing access to IRemUnknown */
70  MSHCTX dest_context; /* context used for activating optimisations (LOCK) */
71  void *dest_context_data; /* reserved context value (LOCK) */
72 };
73 
74 static inline struct proxy_manager *impl_from_IMultiQI( IMultiQI *iface )
75 {
76  return CONTAINING_RECORD(iface, struct proxy_manager, IMultiQI_iface);
77 }
78 
79 static inline struct proxy_manager *impl_from_IMarshal( IMarshal *iface )
80 {
81  return CONTAINING_RECORD(iface, struct proxy_manager, IMarshal_iface);
82 }
83 
85 {
87 }
88 
89 static HRESULT unmarshal_object(const STDOBJREF *stdobjref, APARTMENT *apt,
90  MSHCTX dest_context, void *dest_context_data,
91  REFIID riid, const OXID_INFO *oxid_info,
92  void **object);
93 
94 /* Marshalling just passes a unique identifier to the remote client,
95  * that makes it possible to find the passed interface again.
96  *
97  * So basically we need a set of values that make it unique.
98  *
99  * Note that the IUnknown_QI(ob,xiid,&ppv) always returns the SAME ppv value!
100  *
101  * A triple is used: OXID (apt id), OID (stub manager id),
102  * IPID (interface ptr/stub id).
103  *
104  * OXIDs identify an apartment and are network scoped
105  * OIDs identify a stub manager and are apartment scoped
106  * IPIDs identify an interface stub and are apartment scoped
107  */
108 
110 {
111  HRESULT hr;
112  CLSID clsid;
113 
114  hr = CoGetPSClsid(riid, &clsid);
115  if (hr != S_OK)
116  return hr;
117  return CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER | WINE_CLSCTX_DONT_HOST,
118  NULL, &IID_IPSFactoryBuffer, (LPVOID*)facbuf);
119 }
120 
121 /* marshals an object into a STDOBJREF structure */
123  DWORD dest_context, void *dest_context_data, MSHLFLAGS mshlflags)
124 {
125  struct stub_manager *manager;
126  struct ifstub *ifstub;
127  BOOL tablemarshal;
128  HRESULT hr;
129 
130  hr = apartment_getoxid(apt, &stdobjref->oxid);
131  if (hr != S_OK)
132  return hr;
133 
135  if (hr != S_OK)
136  return hr;
137 
138  if (!(manager = get_stub_manager_from_object(apt, object, TRUE)))
139  return E_OUTOFMEMORY;
140 
141  stdobjref->flags = SORF_NULL;
142  if (mshlflags & MSHLFLAGS_TABLEWEAK)
143  stdobjref->flags |= SORFP_TABLEWEAK;
144  if (mshlflags & MSHLFLAGS_NOPING)
145  stdobjref->flags |= SORF_NOPING;
146  stdobjref->oid = manager->oid;
147 
148  tablemarshal = ((mshlflags & MSHLFLAGS_TABLESTRONG) || (mshlflags & MSHLFLAGS_TABLEWEAK));
149 
150  /* make sure ifstub that we are creating is unique */
151  ifstub = stub_manager_find_ifstub(manager, riid, mshlflags);
152  if (!ifstub) {
154 
155  /* IUnknown doesn't require a stub buffer, because it never goes out on
156  * the wire */
157  if (!IsEqualIID(riid, &IID_IUnknown))
158  {
159  IPSFactoryBuffer *psfb;
160 
161  hr = get_facbuf_for_iid(riid, &psfb);
162  if (hr == S_OK) {
163  hr = IPSFactoryBuffer_CreateStub(psfb, riid, manager->object, &stub);
164  IPSFactoryBuffer_Release(psfb);
165  if (hr != S_OK)
166  ERR("Failed to create an IRpcStubBuffer from IPSFactory for %s with error 0x%08x\n",
167  debugstr_guid(riid), hr);
168  }else {
169  ERR("couldn't get IPSFactory buffer for interface %s\n", debugstr_guid(riid));
170  hr = E_NOINTERFACE;
171  }
172 
173  }
174 
175  if (hr == S_OK) {
176  ifstub = stub_manager_new_ifstub(manager, stub, riid, dest_context, dest_context_data, mshlflags);
177  if (!ifstub)
178  hr = E_OUTOFMEMORY;
179  }
180  if (stub) IRpcStubBuffer_Release(stub);
181 
182  if (hr != S_OK) {
183  stub_manager_int_release(manager);
184  /* destroy the stub manager if it has no ifstubs by releasing
185  * zero external references */
186  stub_manager_ext_release(manager, 0, FALSE, TRUE);
187  return hr;
188  }
189  }
190 
191  if (!tablemarshal)
192  {
193  stdobjref->cPublicRefs = NORMALEXTREFS;
194  stub_manager_ext_addref(manager, stdobjref->cPublicRefs, FALSE);
195  }
196  else
197  {
198  stdobjref->cPublicRefs = 0;
199  if (mshlflags & MSHLFLAGS_TABLESTRONG)
200  stub_manager_ext_addref(manager, 1, FALSE);
201  else
202  stub_manager_ext_addref(manager, 0, TRUE);
203  }
204 
205  /* FIXME: check return value */
207 
208  stdobjref->ipid = ifstub->ipid;
209 
210  stub_manager_int_release(manager);
211  return S_OK;
212 }
213 
214 
215 
216 /* Client-side identity of the server object */
217 
219 static void proxy_manager_destroy(struct proxy_manager * This);
220 static HRESULT proxy_manager_find_ifproxy(struct proxy_manager * This, REFIID riid, struct ifproxy ** ifproxy_found);
222 
224 {
225  HRESULT hr;
226  MULTI_QI mqi;
227 
228  TRACE("%s\n", debugstr_guid(riid));
229 
230  mqi.pIID = riid;
231  hr = IMultiQI_QueryMultipleInterfaces(iface, 1, &mqi);
232  *ppv = mqi.pItf;
233 
234  return hr;
235 }
236 
238 {
239  struct proxy_manager *This = impl_from_IMultiQI(iface);
240  TRACE("%p - before %d\n", iface, This->refs);
241  return InterlockedIncrement(&This->refs);
242 }
243 
245 {
246  struct proxy_manager *This = impl_from_IMultiQI(iface);
248  TRACE("%p - after %d\n", iface, refs);
249  if (!refs)
251  return refs;
252 }
253 
255 {
256  struct proxy_manager *This = impl_from_IMultiQI(iface);
257  REMQIRESULT *qiresults = NULL;
258  ULONG nonlocal_mqis = 0;
259  ULONG i;
260  ULONG successful_mqis = 0;
261  IID *iids = HeapAlloc(GetProcessHeap(), 0, cMQIs * sizeof(*iids));
262  /* mapping of RemQueryInterface index to QueryMultipleInterfaces index */
263  ULONG *mapping = HeapAlloc(GetProcessHeap(), 0, cMQIs * sizeof(*mapping));
264 
265  TRACE("cMQIs: %d\n", cMQIs);
266 
267  /* try to get a local interface - this includes already active proxy
268  * interfaces and also interfaces exposed by the proxy manager */
269  for (i = 0; i < cMQIs; i++)
270  {
271  TRACE("iid[%d] = %s\n", i, debugstr_guid(pMQIs[i].pIID));
272  pMQIs[i].hr = proxy_manager_query_local_interface(This, pMQIs[i].pIID, (void **)&pMQIs[i].pItf);
273  if (pMQIs[i].hr == S_OK)
274  successful_mqis++;
275  else
276  {
277  iids[nonlocal_mqis] = *pMQIs[i].pIID;
278  mapping[nonlocal_mqis] = i;
279  nonlocal_mqis++;
280  }
281  }
282 
283  TRACE("%d interfaces not found locally\n", nonlocal_mqis);
284 
285  /* if we have more than one interface not found locally then we must try
286  * to query the remote object for it */
287  if (nonlocal_mqis != 0)
288  {
290  HRESULT hr;
291  IPID *ipid;
292 
293  /* get the ipid of the first entry */
294  /* FIXME: should we implement ClientIdentity on the ifproxies instead
295  * of the proxy_manager so we use the correct ipid here? */
296  ipid = &LIST_ENTRY(list_head(&This->interfaces), struct ifproxy, entry)->stdobjref.ipid;
297 
298  /* get IRemUnknown proxy so we can communicate with the remote object */
300 
301  if (SUCCEEDED(hr))
302  {
303  hr = IRemUnknown_RemQueryInterface(remunk, ipid, NORMALEXTREFS,
304  nonlocal_mqis, iids, &qiresults);
305  IRemUnknown_Release(remunk);
306  if (FAILED(hr))
307  ERR("IRemUnknown_RemQueryInterface failed with error 0x%08x\n", hr);
308  }
309 
310  /* IRemUnknown_RemQueryInterface can return S_FALSE if only some of
311  * the interfaces were returned */
312  if (SUCCEEDED(hr))
313  {
315 
316  /* try to unmarshal each object returned to us */
317  for (i = 0; i < nonlocal_mqis; i++)
318  {
319  ULONG index = mapping[i];
320  HRESULT hrobj = qiresults[i].hResult;
321  if (hrobj == S_OK)
322  hrobj = unmarshal_object(&qiresults[i].std, apt,
323  This->dest_context,
324  This->dest_context_data,
325  pMQIs[index].pIID, &This->oxid_info,
326  (void **)&pMQIs[index].pItf);
327 
328  if (hrobj == S_OK)
329  successful_mqis++;
330  else
331  ERR("Failed to get pointer to interface %s\n", debugstr_guid(pMQIs[index].pIID));
332  pMQIs[index].hr = hrobj;
333  }
334 
335  apartment_release(apt);
336  }
337 
338  /* free the memory allocated by the proxy */
339  CoTaskMemFree(qiresults);
340  }
341 
342  TRACE("%d/%d successfully queried\n", successful_mqis, cMQIs);
343 
344  HeapFree(GetProcessHeap(), 0, iids);
346 
347  if (successful_mqis == cMQIs)
348  return S_OK; /* we got all requested interfaces */
349  else if (successful_mqis == 0)
350  return E_NOINTERFACE; /* we didn't get any interfaces */
351  else
352  return S_FALSE; /* we got some interfaces */
353 }
354 
355 static const IMultiQIVtbl ClientIdentity_Vtbl =
356 {
361 };
362 
363 static HRESULT StdMarshalImpl_Construct(REFIID, DWORD, void*, void**);
364 
366 {
367  struct proxy_manager *This = impl_from_IMarshal( iface );
368  return IMultiQI_QueryInterface(&This->IMultiQI_iface, riid, ppvObject);
369 }
370 
372 {
373  struct proxy_manager *This = impl_from_IMarshal( iface );
374  return IMultiQI_AddRef(&This->IMultiQI_iface);
375 }
376 
378 {
379  struct proxy_manager *This = impl_from_IMarshal( iface );
380  return IMultiQI_Release(&This->IMultiQI_iface);
381 }
382 
384  IMarshal *iface, REFIID riid, void* pv, DWORD dwDestContext,
385  void* pvDestContext, DWORD mshlflags, CLSID* pCid)
386 {
387  *pCid = CLSID_StdMarshal;
388  return S_OK;
389 }
390 
392  IMarshal *iface, REFIID riid, void* pv, DWORD dwDestContext,
393  void* pvDestContext, DWORD mshlflags, DWORD* pSize)
394 {
395  *pSize = FIELD_OFFSET(OBJREF, u_objref.u_standard.saResAddr.aStringArray);
396  return S_OK;
397 }
398 
399 static void fill_std_objref(OBJREF *objref, const GUID *iid, STDOBJREF *std)
400 {
401  objref->signature = OBJREF_SIGNATURE;
402  objref->flags = OBJREF_STANDARD;
403  objref->iid = *iid;
404  if(std)
405  objref->u_objref.u_standard.std = *std;
406  memset(&objref->u_objref.u_standard.saResAddr, 0,
407  sizeof(objref->u_objref.u_standard.saResAddr));
408 }
409 
411  LPMARSHAL iface, IStream *pStm, REFIID riid, void* pv, DWORD dwDestContext,
412  void* pvDestContext, DWORD mshlflags)
413 {
414  struct proxy_manager *This = impl_from_IMarshal( iface );
415  HRESULT hr;
416  struct ifproxy *ifproxy;
417 
418  TRACE("(...,%s,...)\n", debugstr_guid(riid));
419 
421  if (SUCCEEDED(hr))
422  {
424 
426 
427  if ((mshlflags != MSHLFLAGS_TABLEWEAK) &&
428  (mshlflags != MSHLFLAGS_TABLESTRONG))
429  {
430  ULONG cPublicRefs = ifproxy->refs;
431  ULONG cPublicRefsOld;
432  /* optimization - share out proxy's public references if possible
433  * instead of making new proxy do a roundtrip through the server */
434  do
435  {
436  ULONG cPublicRefsNew;
437  cPublicRefsOld = cPublicRefs;
438  stdobjref.cPublicRefs = cPublicRefs / 2;
439  cPublicRefsNew = cPublicRefs - stdobjref.cPublicRefs;
440  cPublicRefs = InterlockedCompareExchange(
441  (LONG *)&ifproxy->refs, cPublicRefsNew, cPublicRefsOld);
442  } while (cPublicRefs != cPublicRefsOld);
443  }
444 
445  /* normal and table-strong marshaling need at least one reference */
446  if (!stdobjref.cPublicRefs && (mshlflags != MSHLFLAGS_TABLEWEAK))
447  {
448  IRemUnknown *remunk;
450  if (hr == S_OK)
451  {
452  HRESULT hrref = S_OK;
453  REMINTERFACEREF rif;
454  rif.ipid = ifproxy->stdobjref.ipid;
455  rif.cPublicRefs = (mshlflags == MSHLFLAGS_TABLESTRONG) ? 1 : NORMALEXTREFS;
456  rif.cPrivateRefs = 0;
457  hr = IRemUnknown_RemAddRef(remunk, 1, &rif, &hrref);
458  IRemUnknown_Release(remunk);
459  if (hr == S_OK && hrref == S_OK)
460  {
461  /* table-strong marshaling doesn't give the refs to the
462  * client that unmarshals the STDOBJREF */
463  if (mshlflags != MSHLFLAGS_TABLESTRONG)
464  stdobjref.cPublicRefs = rif.cPublicRefs;
465  }
466  else
467  ERR("IRemUnknown_RemAddRef returned with 0x%08x, hrref = 0x%08x\n", hr, hrref);
468  }
469  }
470 
471  if (SUCCEEDED(hr))
472  {
473  OBJREF objref;
474 
475  TRACE("writing stdobjref: flags = %04x cPublicRefs = %d oxid = %s oid = %s ipid = %s\n",
480  fill_std_objref(&objref, riid, &stdobjref);
481  hr = IStream_Write(pStm, &objref, FIELD_OFFSET(OBJREF,
482  u_objref.u_standard.saResAddr.aStringArray), NULL);
483  }
484  }
485  else
486  {
487  /* we don't have the interface already unmarshaled so we have to
488  * request the object from the server */
489  IRemUnknown *remunk;
490  IPID *ipid;
491  REMQIRESULT *qiresults = NULL;
492  IID iid = *riid;
493 
494  /* get the ipid of the first entry */
495  /* FIXME: should we implement ClientIdentity on the ifproxies instead
496  * of the proxy_manager so we use the correct ipid here? */
497  ipid = &LIST_ENTRY(list_head(&This->interfaces), struct ifproxy, entry)->stdobjref.ipid;
498 
499  /* get IRemUnknown proxy so we can communicate with the remote object */
501 
502  if (hr == S_OK)
503  {
504  hr = IRemUnknown_RemQueryInterface(remunk, ipid, NORMALEXTREFS,
505  1, &iid, &qiresults);
506  if (SUCCEEDED(hr))
507  {
508  OBJREF objref;
509 
510  fill_std_objref(&objref, riid, &qiresults->std);
511  hr = IStream_Write(pStm, &objref, FIELD_OFFSET(OBJREF,
512  u_objref.u_standard.saResAddr.aStringArray), NULL);
513  if (FAILED(hr))
514  {
515  REMINTERFACEREF rif;
516  rif.ipid = qiresults->std.ipid;
517  rif.cPublicRefs = qiresults->std.cPublicRefs;
518  rif.cPrivateRefs = 0;
519  IRemUnknown_RemRelease(remunk, 1, &rif);
520  }
521  CoTaskMemFree(qiresults);
522  }
523  else
524  ERR("IRemUnknown_RemQueryInterface failed with error 0x%08x\n", hr);
525  IRemUnknown_Release(remunk);
526  }
527  }
528 
529  return hr;
530 }
531 
533  IMarshal *iface, IStream *pStm, REFIID riid, void **ppv)
534 {
535  struct proxy_manager *This = impl_from_IMarshal( iface );
536  IMarshal *marshal;
537  HRESULT hr;
538 
539  TRACE("(%p, %p, %s, %p)\n", This, pStm, wine_dbgstr_guid(riid), ppv);
540 
541  hr = StdMarshalImpl_Construct(&IID_IMarshal, This->dest_context,
542  This->dest_context_data, (void**)&marshal);
543  if(FAILED(hr))
544  return hr;
545 
546  hr = IMarshal_UnmarshalInterface(marshal, pStm, riid, ppv);
547  IMarshal_Release(marshal);
548  return hr;
549 }
550 
552 {
553  struct proxy_manager *This = impl_from_IMarshal( iface );
554  IMarshal *marshal;
555  HRESULT hr;
556 
557  TRACE("(%p, %p)\n", This, pStm);
558 
559  hr = StdMarshalImpl_Construct(&IID_IMarshal, This->dest_context,
560  This->dest_context_data, (void**)&marshal);
561  if(FAILED(hr))
562  return hr;
563 
564  hr = IMarshal_ReleaseMarshalData(marshal, pStm);
565  IMarshal_Release(marshal);
566  return hr;
567 }
568 
570 {
571  struct proxy_manager *This = impl_from_IMarshal( iface );
572  IMarshal *marshal;
573  HRESULT hr;
574 
575  TRACE("(%p, %x)\n", This, dwReserved);
576 
577  hr = StdMarshalImpl_Construct(&IID_IMarshal, This->dest_context,
578  This->dest_context_data, (void**)&marshal);
579  if(FAILED(hr))
580  return hr;
581 
582  hr = IMarshal_DisconnectObject(marshal, dwReserved);
583  IMarshal_Release(marshal);
584  return hr;
585 }
586 
587 static const IMarshalVtbl ProxyMarshal_Vtbl =
588 {
590  Proxy_AddRef,
598 };
599 
601 {
602  struct proxy_manager *This = impl_from_IClientSecurity( iface );
603  return IMultiQI_QueryInterface(&This->IMultiQI_iface, riid, ppvObject);
604 }
605 
607 {
608  struct proxy_manager *This = impl_from_IClientSecurity( iface );
609  return IMultiQI_AddRef(&This->IMultiQI_iface);
610 }
611 
613 {
614  struct proxy_manager *This = impl_from_IClientSecurity( iface );
615  return IMultiQI_Release(&This->IMultiQI_iface);
616 }
617 
619  IUnknown *pProxy,
620  DWORD *pAuthnSvc,
621  DWORD *pAuthzSvc,
622  OLECHAR **ppServerPrincName,
623  DWORD *pAuthnLevel,
624  DWORD *pImpLevel,
625  void **pAuthInfo,
626  DWORD *pCapabilities)
627 {
628  FIXME("(%p, %p, %p, %p, %p, %p, %p, %p): stub\n", pProxy, pAuthnSvc,
629  pAuthzSvc, ppServerPrincName, pAuthnLevel, pImpLevel, pAuthInfo,
630  pCapabilities);
631 
632  if (pAuthnSvc)
633  *pAuthnSvc = 0;
634  if (pAuthzSvc)
635  *pAuthzSvc = 0;
636  if (ppServerPrincName)
637  *ppServerPrincName = NULL;
638  if (pAuthnLevel)
639  *pAuthnLevel = RPC_C_AUTHN_LEVEL_DEFAULT;
640  if (pImpLevel)
641  *pImpLevel = RPC_C_IMP_LEVEL_DEFAULT;
642  if (pAuthInfo)
643  *pAuthInfo = NULL;
644  if (pCapabilities)
645  *pCapabilities = EOAC_NONE;
646 
647  return E_NOTIMPL;
648 }
649 
651  IUnknown *pProxy, DWORD AuthnSvc,
652  DWORD AuthzSvc,
653  OLECHAR *pServerPrincName,
654  DWORD AuthnLevel, DWORD ImpLevel,
655  void *pAuthInfo,
657 {
658  FIXME("(%p, %d, %d, %s, %d, %d, %p, 0x%x): stub\n", pProxy, AuthnSvc, AuthzSvc,
659  pServerPrincName == COLE_DEFAULT_PRINCIPAL ? "<default principal>" : debugstr_w(pServerPrincName),
660  AuthnLevel, ImpLevel, pAuthInfo, Capabilities);
661  return E_NOTIMPL;
662 }
663 
665  IUnknown *pProxy, IUnknown **ppCopy)
666 {
667  FIXME("(%p, %p): stub\n", pProxy, ppCopy);
668  *ppCopy = NULL;
669  return E_NOTIMPL;
670 }
671 
672 static const IClientSecurityVtbl ProxyCliSec_Vtbl =
673 {
680 };
681 
683 {
684  HRESULT hr = S_OK;
685 
686  if (WAIT_OBJECT_0 != WaitForSingleObject(This->parent->remoting_mutex, INFINITE))
687  {
688  ERR("Wait failed for ifproxy %p\n", This);
689  return E_UNEXPECTED;
690  }
691 
692  if (This->refs == 0)
693  {
695 
696  TRACE("getting public ref for ifproxy %p\n", This);
697 
699  if (hr == S_OK)
700  {
701  HRESULT hrref = S_OK;
702  REMINTERFACEREF rif;
703  rif.ipid = This->stdobjref.ipid;
704  rif.cPublicRefs = NORMALEXTREFS;
705  rif.cPrivateRefs = 0;
706  hr = IRemUnknown_RemAddRef(remunk, 1, &rif, &hrref);
707  IRemUnknown_Release(remunk);
708  if (hr == S_OK && hrref == S_OK)
710  else
711  ERR("IRemUnknown_RemAddRef returned with 0x%08x, hrref = 0x%08x\n", hr, hrref);
712  }
713  }
714  ReleaseMutex(This->parent->remoting_mutex);
715 
716  return hr;
717 }
718 
720 {
721  HRESULT hr = S_OK;
722  LONG public_refs;
723 
724  if (WAIT_OBJECT_0 != WaitForSingleObject(This->parent->remoting_mutex, INFINITE))
725  {
726  ERR("Wait failed for ifproxy %p\n", This);
727  return E_UNEXPECTED;
728  }
729 
730  public_refs = This->refs;
731  if (public_refs > 0)
732  {
734 
735  TRACE("releasing %d refs\n", public_refs);
736 
738  if (hr == S_OK)
739  {
740  REMINTERFACEREF rif;
741  rif.ipid = This->stdobjref.ipid;
742  rif.cPublicRefs = public_refs;
743  rif.cPrivateRefs = 0;
744  hr = IRemUnknown_RemRelease(remunk, 1, &rif);
745  IRemUnknown_Release(remunk);
746  if (hr == S_OK)
747  InterlockedExchangeAdd((LONG *)&This->refs, -public_refs);
748  else if (hr == RPC_E_DISCONNECTED)
749  WARN("couldn't release references because object was "
750  "disconnected: oxid = %s, oid = %s\n",
751  wine_dbgstr_longlong(This->parent->oxid),
752  wine_dbgstr_longlong(This->parent->oid));
753  else
754  ERR("IRemUnknown_RemRelease failed with error 0x%08x\n", hr);
755  }
756  }
757  ReleaseMutex(This->parent->remoting_mutex);
758 
759  return hr;
760 }
761 
762 /* should be called inside This->parent->cs critical section */
763 static void ifproxy_disconnect(struct ifproxy * This)
764 {
766  if (This->proxy) IRpcProxyBuffer_Disconnect(This->proxy);
767 
768  IRpcChannelBuffer_Release(This->chan);
769  This->chan = NULL;
770 }
771 
772 /* should be called in This->parent->cs critical section if it is an entry in parent's list */
773 static void ifproxy_destroy(struct ifproxy * This)
774 {
775  TRACE("%p\n", This);
776 
777  /* release public references to this object so that the stub can know
778  * when to destroy itself */
780 
781  list_remove(&This->entry);
782 
783  if (This->chan)
784  {
785  IRpcChannelBuffer_Release(This->chan);
786  This->chan = NULL;
787  }
788 
789  if (This->proxy) IRpcProxyBuffer_Release(This->proxy);
790 
792 }
793 
796  const OXID_INFO *oxid_info, struct proxy_manager ** proxy_manager)
797 {
798  struct proxy_manager * This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
799  if (!This) return E_OUTOFMEMORY;
800 
801  This->remoting_mutex = CreateMutexW(NULL, FALSE, NULL);
802  if (!This->remoting_mutex)
803  {
806  }
807 
808  if (oxid_info)
809  {
810  This->oxid_info.dwPid = oxid_info->dwPid;
811  This->oxid_info.dwTid = oxid_info->dwTid;
812  This->oxid_info.ipidRemUnknown = oxid_info->ipidRemUnknown;
813  This->oxid_info.dwAuthnHint = oxid_info->dwAuthnHint;
814  This->oxid_info.psa = NULL /* FIXME: copy from oxid_info */;
815  }
816  else
817  {
818  HRESULT hr = RPC_ResolveOxid(oxid, &This->oxid_info);
819  if (FAILED(hr))
820  {
821  CloseHandle(This->remoting_mutex);
823  return hr;
824  }
825  }
826 
827  This->IMultiQI_iface.lpVtbl = &ClientIdentity_Vtbl;
828  This->IMarshal_iface.lpVtbl = &ProxyMarshal_Vtbl;
829  This->IClientSecurity_iface.lpVtbl = &ProxyCliSec_Vtbl;
830 
831  list_init(&This->entry);
832  list_init(&This->interfaces);
833 
835  DEBUG_SET_CRITSEC_NAME(&This->cs, "proxy_manager");
836 
837  /* the apartment the object was unmarshaled into */
838  This->parent = apt;
839 
840  /* the source apartment and id of the object */
841  This->oxid = oxid;
842  This->oid = oid;
843 
844  This->refs = 1;
845 
846  /* the DCOM draft specification states that the SORF_NOPING flag is
847  * proxy manager specific, not ifproxy specific, so this implies that we
848  * should store the STDOBJREF flags here in the proxy manager. */
849  This->sorflags = sorflags;
850 
851  /* we create the IRemUnknown proxy on demand */
852  This->remunk = NULL;
853 
854  /* initialise these values to the weakest values and they will be
855  * overwritten in proxy_manager_set_context */
856  This->dest_context = MSHCTX_INPROC;
857  This->dest_context_data = NULL;
858 
859  EnterCriticalSection(&apt->cs);
860  /* FIXME: we are dependent on the ordering in here to make sure a proxy's
861  * IRemUnknown proxy doesn't get destroyed before the regular proxy does
862  * because we need the IRemUnknown proxy during the destruction of the
863  * regular proxy. Ideally, we should maintain a separate list for the
864  * IRemUnknown proxies that need late destruction */
865  list_add_tail(&apt->proxies, &This->entry);
866  LeaveCriticalSection(&apt->cs);
867 
868  TRACE("%p created for OXID %s, OID %s\n", This,
870 
871  *proxy_manager = This;
872  return S_OK;
873 }
874 
876 {
877  MSHCTX old_dest_context;
878  MSHCTX new_dest_context;
879 
880  do
881  {
882  old_dest_context = This->dest_context;
883  new_dest_context = old_dest_context;
884  /* "stronger" values overwrite "weaker" values. stronger values are
885  * ones that disable more optimisations */
886  switch (old_dest_context)
887  {
888  case MSHCTX_INPROC:
889  new_dest_context = dest_context;
890  break;
891  case MSHCTX_CROSSCTX:
892  switch (dest_context)
893  {
894  case MSHCTX_INPROC:
895  break;
896  default:
897  new_dest_context = dest_context;
898  }
899  break;
900  case MSHCTX_LOCAL:
901  switch (dest_context)
902  {
903  case MSHCTX_INPROC:
904  case MSHCTX_CROSSCTX:
905  break;
906  default:
907  new_dest_context = dest_context;
908  }
909  break;
910  case MSHCTX_NOSHAREDMEM:
911  switch (dest_context)
912  {
913  case MSHCTX_DIFFERENTMACHINE:
914  new_dest_context = dest_context;
915  break;
916  default:
917  break;
918  }
919  break;
920  default:
921  break;
922  }
923 
924  if (old_dest_context == new_dest_context) break;
925 
926  new_dest_context = InterlockedCompareExchange((PLONG)&This->dest_context, new_dest_context, old_dest_context);
927  } while (new_dest_context != old_dest_context);
928 
929  if (dest_context_data)
930  InterlockedExchangePointer(&This->dest_context_data, dest_context_data);
931 }
932 
934 {
935  HRESULT hr;
936  struct ifproxy * ifproxy;
937 
938  TRACE("%s\n", debugstr_guid(riid));
939 
940  if (IsEqualIID(riid, &IID_IUnknown) ||
941  IsEqualIID(riid, &IID_IMultiQI))
942  {
943  *ppv = &This->IMultiQI_iface;
944  IMultiQI_AddRef(&This->IMultiQI_iface);
945  return S_OK;
946  }
947  if (IsEqualIID(riid, &IID_IMarshal))
948  {
949  *ppv = &This->IMarshal_iface;
950  IMarshal_AddRef(&This->IMarshal_iface);
951  return S_OK;
952  }
953  if (IsEqualIID(riid, &IID_IClientSecurity))
954  {
955  *ppv = &This->IClientSecurity_iface;
956  IClientSecurity_AddRef(&This->IClientSecurity_iface);
957  return S_OK;
958  }
959 
961  if (hr == S_OK)
962  {
963  *ppv = ifproxy->iface;
964  IUnknown_AddRef((IUnknown *)*ppv);
965  return S_OK;
966  }
967 
968  *ppv = NULL;
969  return E_NOINTERFACE;
970 }
971 
973  struct proxy_manager * This, const STDOBJREF *stdobjref, REFIID riid,
974  IRpcChannelBuffer * channel, struct ifproxy ** iif_out)
975 {
976  HRESULT hr;
977  IPSFactoryBuffer * psfb;
978  struct ifproxy * ifproxy = HeapAlloc(GetProcessHeap(), 0, sizeof(*ifproxy));
979  if (!ifproxy) return E_OUTOFMEMORY;
980 
982 
983  ifproxy->parent = This;
985  ifproxy->iid = *riid;
986  ifproxy->refs = 0;
987  ifproxy->proxy = NULL;
988 
989  assert(channel);
990  ifproxy->chan = channel; /* FIXME: we should take the binding strings and construct the channel in this function */
991 
992  /* the IUnknown interface is special because it does not have a
993  * proxy associated with the ifproxy as we handle IUnknown ourselves */
995  {
996  ifproxy->iface = &This->IMultiQI_iface;
997  IMultiQI_AddRef(&This->IMultiQI_iface);
998  hr = S_OK;
999  }
1000  else
1001  {
1002  hr = get_facbuf_for_iid(riid, &psfb);
1003  if (hr == S_OK)
1004  {
1005  /* important note: the outer unknown is set to the proxy manager.
1006  * This ensures the COM identity rules are not violated, by having a
1007  * one-to-one mapping of objects on the proxy side to objects on the
1008  * stub side, no matter which interface you view the object through */
1009  hr = IPSFactoryBuffer_CreateProxy(psfb, (IUnknown*)&This->IMultiQI_iface, riid,
1010  &ifproxy->proxy, &ifproxy->iface);
1011  IPSFactoryBuffer_Release(psfb);
1012  if (hr != S_OK)
1013  ERR("Could not create proxy for interface %s, error 0x%08x\n",
1014  debugstr_guid(riid), hr);
1015  }
1016  else
1017  ERR("Could not get IPSFactoryBuffer for interface %s, error 0x%08x\n",
1018  debugstr_guid(riid), hr);
1019 
1020  if (hr == S_OK)
1021  hr = IRpcProxyBuffer_Connect(ifproxy->proxy, ifproxy->chan);
1022  }
1023 
1024  if (hr == S_OK)
1025  {
1026  EnterCriticalSection(&This->cs);
1027  list_add_tail(&This->interfaces, &ifproxy->entry);
1028  LeaveCriticalSection(&This->cs);
1029 
1030  *iif_out = ifproxy;
1031  TRACE("ifproxy %p created for IPID %s, interface %s with %u public refs\n",
1033  }
1034  else
1036 
1037  return hr;
1038 }
1039 
1040 static HRESULT proxy_manager_find_ifproxy(struct proxy_manager * This, REFIID riid, struct ifproxy ** ifproxy_found)
1041 {
1042  HRESULT hr = E_NOINTERFACE; /* assume not found */
1043  struct list * cursor;
1044 
1045  EnterCriticalSection(&This->cs);
1046  LIST_FOR_EACH(cursor, &This->interfaces)
1047  {
1048  struct ifproxy * ifproxy = LIST_ENTRY(cursor, struct ifproxy, entry);
1049  if (IsEqualIID(riid, &ifproxy->iid))
1050  {
1051  *ifproxy_found = ifproxy;
1052  hr = S_OK;
1053  break;
1054  }
1055  }
1056  LeaveCriticalSection(&This->cs);
1057 
1058  return hr;
1059 }
1060 
1062 {
1063  struct list * cursor;
1064 
1065  TRACE("oxid = %s, oid = %s\n", wine_dbgstr_longlong(This->oxid),
1066  wine_dbgstr_longlong(This->oid));
1067 
1068  EnterCriticalSection(&This->cs);
1069 
1070  /* SORFP_NOLIFTIMEMGMT proxies (for IRemUnknown) shouldn't be
1071  * disconnected - it won't do anything anyway, except cause
1072  * problems for other objects that depend on this proxy always
1073  * working */
1074  if (!(This->sorflags & SORFP_NOLIFETIMEMGMT))
1075  {
1076  LIST_FOR_EACH(cursor, &This->interfaces)
1077  {
1078  struct ifproxy * ifproxy = LIST_ENTRY(cursor, struct ifproxy, entry);
1080  }
1081  }
1082 
1083  /* apartment is being destroyed so don't keep a pointer around to it */
1084  This->parent = NULL;
1085 
1086  LeaveCriticalSection(&This->cs);
1087 }
1088 
1090 {
1091  HRESULT hr = S_OK;
1092  struct apartment *apt;
1093  BOOL called_in_original_apt;
1094 
1095  /* we don't want to try and unmarshal or use IRemUnknown if we don't want
1096  * lifetime management */
1097  if (This->sorflags & SORFP_NOLIFETIMEMGMT)
1098  return S_FALSE;
1099 
1100  if (!(apt = apartment_get_current_or_mta()))
1101  return CO_E_NOTINITIALIZED;
1102 
1103  called_in_original_apt = This->parent && (This->parent->oxid == apt->oxid);
1104 
1105  EnterCriticalSection(&This->cs);
1106  /* only return the cached object if called from the original apartment.
1107  * in future, we might want to make the IRemUnknown proxy callable from any
1108  * apartment to avoid these checks */
1109  if (This->remunk && called_in_original_apt)
1110  {
1111  /* already created - return existing object */
1112  *remunk = This->remunk;
1113  IRemUnknown_AddRef(*remunk);
1114  }
1115  else if (!This->parent)
1116  {
1117  /* disconnected - we can't create IRemUnknown */
1118  *remunk = NULL;
1119  hr = S_FALSE;
1120  }
1121  else
1122  {
1123  STDOBJREF stdobjref;
1124  /* Don't want IRemUnknown lifetime management as this is IRemUnknown!
1125  * We also don't care about whether or not the stub is still alive */
1126  stdobjref.flags = SORFP_NOLIFETIMEMGMT | SORF_NOPING;
1127  stdobjref.cPublicRefs = 1;
1128  /* oxid of destination object */
1129  stdobjref.oxid = This->oxid;
1130  /* FIXME: what should be used for the oid? The DCOM draft doesn't say */
1131  stdobjref.oid = (OID)-1;
1132  stdobjref.ipid = This->oxid_info.ipidRemUnknown;
1133 
1134  /* do the unmarshal */
1135  hr = unmarshal_object(&stdobjref, apt, This->dest_context,
1136  This->dest_context_data, &IID_IRemUnknown,
1137  &This->oxid_info, (void**)remunk);
1138  if (hr == S_OK && called_in_original_apt)
1139  {
1140  This->remunk = *remunk;
1141  IRemUnknown_AddRef(This->remunk);
1142  }
1143  }
1144  LeaveCriticalSection(&This->cs);
1145  apartment_release(apt);
1146 
1147  TRACE("got IRemUnknown* pointer %p, hr = 0x%08x\n", *remunk, hr);
1148 
1149  return hr;
1150 }
1151 
1152 /* destroys a proxy manager, freeing the memory it used.
1153  * Note: this function should not be called from a list iteration in the
1154  * apartment, due to the fact that it removes itself from the apartment and
1155  * it could add a proxy to IRemUnknown into the apartment. */
1157 {
1158  struct list * cursor;
1159 
1160  TRACE("oxid = %s, oid = %s\n", wine_dbgstr_longlong(This->oxid),
1161  wine_dbgstr_longlong(This->oid));
1162 
1163  if (This->parent)
1164  {
1165  EnterCriticalSection(&This->parent->cs);
1166 
1167  /* remove ourself from the list of proxy objects in the apartment */
1168  LIST_FOR_EACH(cursor, &This->parent->proxies)
1169  {
1170  if (cursor == &This->entry)
1171  {
1172  list_remove(&This->entry);
1173  break;
1174  }
1175  }
1176 
1177  LeaveCriticalSection(&This->parent->cs);
1178  }
1179 
1180  /* destroy all of the interface proxies */
1181  while ((cursor = list_head(&This->interfaces)))
1182  {
1183  struct ifproxy * ifproxy = LIST_ENTRY(cursor, struct ifproxy, entry);
1185  }
1186 
1187  if (This->remunk) IRemUnknown_Release(This->remunk);
1188  CoTaskMemFree(This->oxid_info.psa);
1189 
1192 
1193  CloseHandle(This->remoting_mutex);
1194 
1195  HeapFree(GetProcessHeap(), 0, This);
1196 }
1197 
1198 /* finds the proxy manager corresponding to a given OXID and OID that has
1199  * been unmarshaled in the specified apartment. The caller must release the
1200  * reference to the proxy_manager when the object is no longer used. */
1201 static BOOL find_proxy_manager(APARTMENT * apt, OXID oxid, OID oid, struct proxy_manager ** proxy_found)
1202 {
1203  BOOL found = FALSE;
1204  struct list * cursor;
1205 
1206  EnterCriticalSection(&apt->cs);
1207  LIST_FOR_EACH(cursor, &apt->proxies)
1208  {
1209  struct proxy_manager * proxy = LIST_ENTRY(cursor, struct proxy_manager, entry);
1210  if ((oxid == proxy->oxid) && (oid == proxy->oid))
1211  {
1212  /* be careful of a race with ClientIdentity_Release, which would
1213  * cause us to return a proxy which is in the process of being
1214  * destroyed */
1215  if (IMultiQI_AddRef(&proxy->IMultiQI_iface) != 0)
1216  {
1217  *proxy_found = proxy;
1218  found = TRUE;
1219  break;
1220  }
1221  }
1222  }
1223  LeaveCriticalSection(&apt->cs);
1224  return found;
1225 }
1226 
1228 {
1229  struct list * cursor;
1230 
1231  LIST_FOR_EACH(cursor, &apt->proxies)
1232  {
1233  struct proxy_manager * proxy = LIST_ENTRY(cursor, struct proxy_manager, entry);
1235  }
1236 
1237  return S_OK;
1238 }
1239 
1240 /********************** StdMarshal implementation ****************************/
1241 typedef struct _StdMarshalImpl
1242 {
1247 } StdMarshalImpl;
1248 
1250 {
1251  return CONTAINING_RECORD(iface, StdMarshalImpl, IMarshal_iface);
1252 }
1253 
1254 static HRESULT WINAPI
1256 {
1257  *ppv = NULL;
1258  if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IMarshal, riid))
1259  {
1260  *ppv = iface;
1261  IMarshal_AddRef(iface);
1262  return S_OK;
1263  }
1264  FIXME("No interface for %s.\n", debugstr_guid(riid));
1265  return E_NOINTERFACE;
1266 }
1267 
1268 static ULONG WINAPI
1270 {
1272  return InterlockedIncrement(&This->ref);
1273 }
1274 
1275 static ULONG WINAPI
1277 {
1280 
1281  if (!ref) HeapFree(GetProcessHeap(),0,This);
1282  return ref;
1283 }
1284 
1285 static HRESULT WINAPI
1287  IMarshal *iface, REFIID riid, void* pv, DWORD dwDestContext,
1288  void* pvDestContext, DWORD mshlflags, CLSID* pCid)
1289 {
1290  *pCid = CLSID_StdMarshal;
1291  return S_OK;
1292 }
1293 
1294 static HRESULT WINAPI
1296  IMarshal *iface, REFIID riid, void* pv, DWORD dwDestContext,
1297  void* pvDestContext, DWORD mshlflags, DWORD* pSize)
1298 {
1299  *pSize = FIELD_OFFSET(OBJREF, u_objref.u_standard.saResAddr.aStringArray);
1300  return S_OK;
1301 }
1302 
1303 static HRESULT WINAPI
1305  IMarshal *iface, IStream *pStm,REFIID riid, void* pv, DWORD dest_context,
1306  void* dest_context_data, DWORD mshlflags)
1307 {
1308  ULONG res;
1309  HRESULT hres;
1310  APARTMENT *apt;
1311  OBJREF objref;
1312 
1313  TRACE("(...,%s,...)\n", debugstr_guid(riid));
1314 
1315  if (!(apt = apartment_get_current_or_mta()))
1316  {
1317  ERR("Apartment not initialized\n");
1318  return CO_E_NOTINITIALIZED;
1319  }
1320 
1321  /* make sure this apartment can be reached from other threads / processes */
1322  RPC_StartRemoting(apt);
1323 
1324  fill_std_objref(&objref, riid, NULL);
1325  hres = marshal_object(apt, &objref.u_objref.u_standard.std, riid,
1326  pv, dest_context, dest_context_data, mshlflags);
1327  apartment_release(apt);
1328  if (hres != S_OK)
1329  {
1330  ERR("Failed to create ifstub, hres=0x%x\n", hres);
1331  return hres;
1332  }
1333 
1334  return IStream_Write(pStm, &objref,
1335  FIELD_OFFSET(OBJREF, u_objref.u_standard.saResAddr.aStringArray), &res);
1336 }
1337 
1338 /* helper for StdMarshalImpl_UnmarshalInterface - does the unmarshaling with
1339  * no questions asked about the rules surrounding same-apartment unmarshals
1340  * and table marshaling */
1341 static HRESULT unmarshal_object(const STDOBJREF *stdobjref, APARTMENT *apt,
1342  MSHCTX dest_context, void *dest_context_data,
1343  REFIID riid, const OXID_INFO *oxid_info,
1344  void **object)
1345 {
1346  struct proxy_manager *proxy_manager = NULL;
1347  HRESULT hr = S_OK;
1348 
1349  assert(apt);
1350 
1351  TRACE("stdobjref: flags = %04x cPublicRefs = %d oxid = %s oid = %s ipid = %s\n",
1352  stdobjref->flags, stdobjref->cPublicRefs,
1353  wine_dbgstr_longlong(stdobjref->oxid),
1354  wine_dbgstr_longlong(stdobjref->oid),
1355  debugstr_guid(&stdobjref->ipid));
1356 
1357  /* create a new proxy manager if one doesn't already exist for the
1358  * object */
1359  if (!find_proxy_manager(apt, stdobjref->oxid, stdobjref->oid, &proxy_manager))
1360  {
1361  hr = proxy_manager_construct(apt, stdobjref->flags,
1362  stdobjref->oxid, stdobjref->oid, oxid_info,
1363  &proxy_manager);
1364  }
1365  else
1366  TRACE("proxy manager already created, using\n");
1367 
1368  if (hr == S_OK)
1369  {
1370  struct ifproxy * ifproxy;
1371 
1372  proxy_manager_set_context(proxy_manager, dest_context, dest_context_data);
1373 
1375  if (hr == E_NOINTERFACE)
1376  {
1377  IRpcChannelBuffer *chanbuf;
1382  &chanbuf, apt);
1383  if (hr == S_OK)
1385  riid, chanbuf, &ifproxy);
1386  }
1387  else
1388  IUnknown_AddRef((IUnknown *)ifproxy->iface);
1389 
1390  if (hr == S_OK)
1391  {
1393  /* get at least one external reference to the object to keep it alive */
1395  if (FAILED(hr))
1397  }
1398 
1399  if (hr == S_OK)
1400  *object = ifproxy->iface;
1401  }
1402 
1403  /* release our reference to the proxy manager - the client/apartment
1404  * will hold on to the remaining reference for us */
1405  if (proxy_manager) IMultiQI_Release(&proxy_manager->IMultiQI_iface);
1406 
1407  return hr;
1408 }
1409 
1410 static HRESULT std_unmarshal_interface(MSHCTX dest_context, void *dest_context_data,
1411  IStream *pStm, REFIID riid, void **ppv)
1412 {
1413  struct stub_manager *stubmgr = NULL;
1414  struct OR_STANDARD obj;
1415  ULONG res;
1416  HRESULT hres;
1417  APARTMENT *apt;
1418  APARTMENT *stub_apt;
1419  OXID oxid;
1420 
1421  TRACE("(...,%s,....)\n", debugstr_guid(riid));
1422 
1423  /* we need an apartment to unmarshal into */
1424  if (!(apt = apartment_get_current_or_mta()))
1425  {
1426  ERR("Apartment not initialized\n");
1427  return CO_E_NOTINITIALIZED;
1428  }
1429 
1430  /* read STDOBJREF from wire */
1431  hres = IStream_Read(pStm, &obj, FIELD_OFFSET(struct OR_STANDARD, saResAddr.aStringArray), &res);
1432  if (hres != S_OK)
1433  {
1434  apartment_release(apt);
1435  return STG_E_READFAULT;
1436  }
1437 
1438  hres = apartment_getoxid(apt, &oxid);
1439  if (hres != S_OK)
1440  {
1441  apartment_release(apt);
1442  return hres;
1443  }
1444 
1445  if (obj.saResAddr.wNumEntries)
1446  {
1447  ERR("unsupported size of DUALSTRINGARRAY\n");
1448  return E_NOTIMPL;
1449  }
1450 
1451  /* check if we're marshalling back to ourselves */
1452  if ((oxid == obj.std.oxid) && (stubmgr = get_stub_manager(apt, obj.std.oid)))
1453  {
1454  TRACE("Unmarshalling object marshalled in same apartment for iid %s, "
1455  "returning original object %p\n", debugstr_guid(riid), stubmgr->object);
1456 
1457  hres = IUnknown_QueryInterface(stubmgr->object, riid, ppv);
1458 
1459  /* unref the ifstub. FIXME: only do this on success? */
1460  if (!stub_manager_is_table_marshaled(stubmgr, &obj.std.ipid))
1461  stub_manager_ext_release(stubmgr, obj.std.cPublicRefs, obj.std.flags & SORFP_TABLEWEAK, FALSE);
1462 
1463  stub_manager_int_release(stubmgr);
1464  apartment_release(apt);
1465  return hres;
1466  }
1467 
1468  /* notify stub manager about unmarshal if process-local object.
1469  * note: if the oxid is not found then we and native will quite happily
1470  * ignore table marshaling and normal marshaling rules regarding number of
1471  * unmarshals, etc, but if you abuse these rules then your proxy could end
1472  * up returning RPC_E_DISCONNECTED. */
1473  if ((stub_apt = apartment_findfromoxid(obj.std.oxid, TRUE)))
1474  {
1475  if ((stubmgr = get_stub_manager(stub_apt, obj.std.oid)))
1476  {
1477  if (!stub_manager_notify_unmarshal(stubmgr, &obj.std.ipid))
1479  }
1480  else
1481  {
1482  WARN("Couldn't find object for OXID %s, OID %s, assuming disconnected\n",
1483  wine_dbgstr_longlong(obj.std.oxid),
1484  wine_dbgstr_longlong(obj.std.oid));
1486  }
1487  }
1488  else
1489  TRACE("Treating unmarshal from OXID %s as inter-process\n",
1490  wine_dbgstr_longlong(obj.std.oxid));
1491 
1492  if (hres == S_OK)
1493  hres = unmarshal_object(&obj.std, apt, dest_context,
1494  dest_context_data, riid,
1495  stubmgr ? &stubmgr->oxid_info : NULL, ppv);
1496 
1497  if (stubmgr) stub_manager_int_release(stubmgr);
1498  if (stub_apt) apartment_release(stub_apt);
1499 
1500  if (hres != S_OK) WARN("Failed with error 0x%08x\n", hres);
1501  else TRACE("Successfully created proxy %p\n", *ppv);
1502 
1503  apartment_release(apt);
1504  return hres;
1505 }
1506 
1507 static HRESULT WINAPI
1509 {
1511  OBJREF objref;
1512  HRESULT hr;
1513  ULONG res;
1514 
1515  hr = IStream_Read(pStm, &objref, FIELD_OFFSET(OBJREF, u_objref), &res);
1516  if (hr != S_OK || (res != FIELD_OFFSET(OBJREF, u_objref)))
1517  {
1518  ERR("Failed to read common OBJREF header, 0x%08x\n", hr);
1519  return STG_E_READFAULT;
1520  }
1521 
1522  if (objref.signature != OBJREF_SIGNATURE)
1523  {
1524  ERR("Bad OBJREF signature 0x%08x\n", objref.signature);
1525  return RPC_E_INVALID_OBJREF;
1526  }
1527 
1528  if (!(objref.flags & OBJREF_STANDARD))
1529  {
1530  FIXME("unsupported objref.flags = %x\n", objref.flags);
1531  return E_NOTIMPL;
1532  }
1533 
1534  return std_unmarshal_interface(This->dest_context,
1535  This->dest_context_data, pStm, riid, ppv);
1536 }
1537 
1539 {
1540  struct OR_STANDARD obj;
1541  ULONG res;
1542  HRESULT hres;
1543  struct stub_manager *stubmgr;
1544  APARTMENT *apt;
1545 
1546  hres = IStream_Read(pStm, &obj, FIELD_OFFSET(struct OR_STANDARD, saResAddr.aStringArray), &res);
1547  if (hres != S_OK) return STG_E_READFAULT;
1548 
1549  if (obj.saResAddr.wNumEntries)
1550  {
1551  ERR("unsupported size of DUALSTRINGARRAY\n");
1552  return E_NOTIMPL;
1553  }
1554 
1555  TRACE("oxid = %s, oid = %s, ipid = %s\n",
1556  wine_dbgstr_longlong(obj.std.oxid),
1557  wine_dbgstr_longlong(obj.std.oid),
1558  wine_dbgstr_guid(&obj.std.ipid));
1559 
1560  if (!(apt = apartment_findfromoxid(obj.std.oxid, TRUE)))
1561  {
1562  WARN("Could not map OXID %s to apartment object\n",
1563  wine_dbgstr_longlong(obj.std.oxid));
1564  return RPC_E_INVALID_OBJREF;
1565  }
1566 
1567  if (!(stubmgr = get_stub_manager(apt, obj.std.oid)))
1568  {
1570  ERR("could not map object ID to stub manager, oxid=%s, oid=%s\n",
1571  wine_dbgstr_longlong(obj.std.oxid), wine_dbgstr_longlong(obj.std.oid));
1572  return RPC_E_INVALID_OBJREF;
1573  }
1574 
1575  stub_manager_release_marshal_data(stubmgr, obj.std.cPublicRefs, &obj.std.ipid, obj.std.flags & SORFP_TABLEWEAK);
1576 
1577  stub_manager_int_release(stubmgr);
1579 
1580  return S_OK;
1581 }
1582 
1583 static HRESULT WINAPI
1585 {
1586  OBJREF objref;
1587  HRESULT hr;
1588  ULONG res;
1589 
1590  TRACE("iface=%p, pStm=%p\n", iface, pStm);
1591 
1592  hr = IStream_Read(pStm, &objref, FIELD_OFFSET(OBJREF, u_objref), &res);
1593  if (hr != S_OK || (res != FIELD_OFFSET(OBJREF, u_objref)))
1594  {
1595  ERR("Failed to read common OBJREF header, 0x%08x\n", hr);
1596  return STG_E_READFAULT;
1597  }
1598 
1599  if (objref.signature != OBJREF_SIGNATURE)
1600  {
1601  ERR("Bad OBJREF signature 0x%08x\n", objref.signature);
1602  return RPC_E_INVALID_OBJREF;
1603  }
1604 
1605  if (!(objref.flags & OBJREF_STANDARD))
1606  {
1607  FIXME("unsupported objref.flags = %x\n", objref.flags);
1608  return E_NOTIMPL;
1609  }
1610 
1611  return std_release_marshal_data(pStm);
1612 }
1613 
1614 static HRESULT WINAPI
1616 {
1617  FIXME("(), stub!\n");
1618  return S_OK;
1619 }
1620 
1621 static const IMarshalVtbl StdMarshalVtbl =
1622 {
1632 };
1633 
1634 static HRESULT StdMarshalImpl_Construct(REFIID riid, DWORD dest_context, void *dest_context_data, void** ppvObject)
1635 {
1636  HRESULT hr;
1637 
1638  StdMarshalImpl *pStdMarshal = HeapAlloc(GetProcessHeap(), 0, sizeof(StdMarshalImpl));
1639  if (!pStdMarshal)
1640  return E_OUTOFMEMORY;
1641 
1642  pStdMarshal->IMarshal_iface.lpVtbl = &StdMarshalVtbl;
1643  pStdMarshal->ref = 0;
1644  pStdMarshal->dest_context = dest_context;
1645  pStdMarshal->dest_context_data = dest_context_data;
1646 
1647  hr = IMarshal_QueryInterface(&pStdMarshal->IMarshal_iface, riid, ppvObject);
1648  if (FAILED(hr))
1649  HeapFree(GetProcessHeap(), 0, pStdMarshal);
1650 
1651  return hr;
1652 }
1653 
1654 /***********************************************************************
1655  * CoGetStandardMarshal [OLE32.@]
1656  *
1657  * Gets or creates a standard marshal object.
1658  *
1659  * PARAMS
1660  * riid [I] Interface identifier of the pUnk object.
1661  * pUnk [I] Optional. Object to get the marshal object for.
1662  * dwDestContext [I] Destination. Used to enable or disable optimizations.
1663  * pvDestContext [I] Reserved. Must be NULL.
1664  * mshlflags [I] Flags affecting the marshaling process.
1665  * ppMarshal [O] Address where marshal object will be stored.
1666  *
1667  * RETURNS
1668  * Success: S_OK.
1669  * Failure: HRESULT code.
1670  *
1671  * NOTES
1672  *
1673  * The function retrieves the IMarshal object associated with an object if
1674  * that object is currently an active stub, otherwise a new marshal object is
1675  * created.
1676  */
1678  DWORD dwDestContext, LPVOID pvDestContext,
1679  DWORD mshlflags, LPMARSHAL *ppMarshal)
1680 {
1681  if (pUnk == NULL)
1682  {
1683  FIXME("(%s,NULL,%x,%p,%x,%p), unimplemented yet.\n",
1684  debugstr_guid(riid),dwDestContext,pvDestContext,mshlflags,ppMarshal);
1685  return E_NOTIMPL;
1686  }
1687  TRACE("(%s,%p,%x,%p,%x,%p)\n",
1688  debugstr_guid(riid),pUnk,dwDestContext,pvDestContext,mshlflags,ppMarshal);
1689 
1690  return StdMarshalImpl_Construct(&IID_IMarshal, dwDestContext, pvDestContext, (void**)ppMarshal);
1691 }
1692 
1693 /***********************************************************************
1694  * get_marshaler [internal]
1695  *
1696  * Retrieves an IMarshal interface for an object.
1697  */
1699  void *pvDestContext, DWORD mshlFlags,
1700  LPMARSHAL *pMarshal)
1701 {
1702  HRESULT hr;
1703 
1704  if (!pUnk)
1705  return E_POINTER;
1706  hr = IUnknown_QueryInterface(pUnk, &IID_IMarshal, (LPVOID*)pMarshal);
1707  if (hr != S_OK)
1708  hr = CoGetStandardMarshal(riid, pUnk, dwDestContext, pvDestContext,
1709  mshlFlags, pMarshal);
1710  return hr;
1711 }
1712 
1713 /***********************************************************************
1714  * get_unmarshaler_from_stream [internal]
1715  *
1716  * Creates an IMarshal* object according to the data marshaled to the stream.
1717  * The function leaves the stream pointer at the start of the data written
1718  * to the stream by the IMarshal* object.
1719  */
1721 {
1722  HRESULT hr;
1723  ULONG res;
1724  OBJREF objref;
1725 
1726  /* read common OBJREF header */
1727  hr = IStream_Read(stream, &objref, FIELD_OFFSET(OBJREF, u_objref), &res);
1728  if (hr != S_OK || (res != FIELD_OFFSET(OBJREF, u_objref)))
1729  {
1730  ERR("Failed to read common OBJREF header, 0x%08x\n", hr);
1731  return STG_E_READFAULT;
1732  }
1733 
1734  /* sanity check on header */
1735  if (objref.signature != OBJREF_SIGNATURE)
1736  {
1737  ERR("Bad OBJREF signature 0x%08x\n", objref.signature);
1738  return RPC_E_INVALID_OBJREF;
1739  }
1740 
1741  if (iid) *iid = objref.iid;
1742 
1743  /* FIXME: handler marshaling */
1744  if (objref.flags & OBJREF_STANDARD)
1745  {
1746  TRACE("Using standard unmarshaling\n");
1747  *marshal = NULL;
1748  return S_FALSE;
1749  }
1750  else if (objref.flags & OBJREF_CUSTOM)
1751  {
1752  ULONG custom_header_size = FIELD_OFFSET(OBJREF, u_objref.u_custom.pData) -
1753  FIELD_OFFSET(OBJREF, u_objref.u_custom);
1754  TRACE("Using custom unmarshaling\n");
1755  /* read constant sized OR_CUSTOM data from stream */
1756  hr = IStream_Read(stream, &objref.u_objref.u_custom,
1757  custom_header_size, &res);
1758  if (hr != S_OK || (res != custom_header_size))
1759  {
1760  ERR("Failed to read OR_CUSTOM header, 0x%08x\n", hr);
1761  return STG_E_READFAULT;
1762  }
1763  /* now create the marshaler specified in the stream */
1764  hr = CoCreateInstance(&objref.u_objref.u_custom.clsid, NULL,
1765  CLSCTX_INPROC_SERVER, &IID_IMarshal,
1766  (LPVOID*)marshal);
1767  }
1768  else
1769  {
1770  FIXME("Invalid or unimplemented marshaling type specified: %x\n",
1771  objref.flags);
1772  return RPC_E_INVALID_OBJREF;
1773  }
1774 
1775  if (hr != S_OK)
1776  ERR("Failed to create marshal, 0x%08x\n", hr);
1777 
1778  return hr;
1779 }
1780 
1781 /***********************************************************************
1782  * CoGetMarshalSizeMax [OLE32.@]
1783  *
1784  * Gets the maximum amount of data that will be needed by a marshal.
1785  *
1786  * PARAMS
1787  * pulSize [O] Address where maximum marshal size will be stored.
1788  * riid [I] Identifier of the interface to marshal.
1789  * pUnk [I] Pointer to the object to marshal.
1790  * dwDestContext [I] Destination. Used to enable or disable optimizations.
1791  * pvDestContext [I] Reserved. Must be NULL.
1792  * mshlFlags [I] Flags that affect the marshaling. See CoMarshalInterface().
1793  *
1794  * RETURNS
1795  * Success: S_OK.
1796  * Failure: HRESULT code.
1797  *
1798  * SEE ALSO
1799  * CoMarshalInterface().
1800  */
1802  DWORD dwDestContext, void *pvDestContext,
1803  DWORD mshlFlags)
1804 {
1805  HRESULT hr;
1806  LPMARSHAL pMarshal;
1807  BOOL std_marshal = FALSE;
1808 
1809  if(!pUnk)
1810  return E_POINTER;
1811 
1812  hr = IUnknown_QueryInterface(pUnk, &IID_IMarshal, (void**)&pMarshal);
1813  if (hr != S_OK)
1814  {
1815  std_marshal = TRUE;
1816  hr = CoGetStandardMarshal(riid, pUnk, dwDestContext, pvDestContext,
1817  mshlFlags, &pMarshal);
1818  }
1819  if (hr != S_OK)
1820  return hr;
1821 
1822  hr = IMarshal_GetMarshalSizeMax(pMarshal, riid, pUnk, dwDestContext,
1823  pvDestContext, mshlFlags, pulSize);
1824  if (!std_marshal)
1825  /* add on the size of the whole OBJREF structure like native does */
1826  *pulSize += sizeof(OBJREF);
1827 
1828  IMarshal_Release(pMarshal);
1829  return hr;
1830 }
1831 
1832 
1833 static void dump_MSHLFLAGS(MSHLFLAGS flags)
1834 {
1835  if (flags & MSHLFLAGS_TABLESTRONG)
1836  TRACE(" MSHLFLAGS_TABLESTRONG");
1837  if (flags & MSHLFLAGS_TABLEWEAK)
1838  TRACE(" MSHLFLAGS_TABLEWEAK");
1839  if (!(flags & (MSHLFLAGS_TABLESTRONG|MSHLFLAGS_TABLEWEAK)))
1840  TRACE(" MSHLFLAGS_NORMAL");
1841  if (flags & MSHLFLAGS_NOPING)
1842  TRACE(" MSHLFLAGS_NOPING");
1843 }
1844 
1845 /***********************************************************************
1846  * CoMarshalInterface [OLE32.@]
1847  *
1848  * Marshals an interface into a stream so that the object can then be
1849  * unmarshaled from another COM apartment and used remotely.
1850  *
1851  * PARAMS
1852  * pStream [I] Stream the object will be marshaled into.
1853  * riid [I] Identifier of the interface to marshal.
1854  * pUnk [I] Pointer to the object to marshal.
1855  * dwDestContext [I] Destination. Used to enable or disable optimizations.
1856  * pvDestContext [I] Reserved. Must be NULL.
1857  * mshlFlags [I] Flags that affect the marshaling. See notes.
1858  *
1859  * RETURNS
1860  * Success: S_OK.
1861  * Failure: HRESULT code.
1862  *
1863  * NOTES
1864  *
1865  * The mshlFlags parameter can take one or more of the following flags:
1866  *| MSHLFLAGS_NORMAL - Unmarshal once, releases stub on last proxy release.
1867  *| MSHLFLAGS_TABLESTRONG - Unmarshal many, release when CoReleaseMarshalData() called.
1868  *| MSHLFLAGS_TABLEWEAK - Unmarshal many, releases stub on last proxy release.
1869  *| MSHLFLAGS_NOPING - No automatic garbage collection (and so reduces network traffic).
1870  *
1871  * If a marshaled object is not unmarshaled, then CoReleaseMarshalData() must
1872  * be called in order to release the resources used in the marshaling.
1873  *
1874  * SEE ALSO
1875  * CoUnmarshalInterface(), CoReleaseMarshalData().
1876  */
1878  DWORD dwDestContext, void *pvDestContext,
1879  DWORD mshlFlags)
1880 {
1881  HRESULT hr;
1882  CLSID marshaler_clsid;
1883  LPMARSHAL pMarshal;
1884 
1885  TRACE("(%p, %s, %p, %x, %p, ", pStream, debugstr_guid(riid), pUnk,
1886  dwDestContext, pvDestContext);
1887  dump_MSHLFLAGS(mshlFlags);
1888  TRACE(")\n");
1889 
1890  if (!pUnk || !pStream)
1891  return E_INVALIDARG;
1892 
1893  /* get the marshaler for the specified interface */
1894  hr = get_marshaler(riid, pUnk, dwDestContext, pvDestContext, mshlFlags, &pMarshal);
1895  if (hr != S_OK)
1896  {
1897  ERR("Failed to get marshaller, 0x%08x\n", hr);
1898  return hr;
1899  }
1900 
1901  hr = IMarshal_GetUnmarshalClass(pMarshal, riid, pUnk, dwDestContext,
1902  pvDestContext, mshlFlags, &marshaler_clsid);
1903  if (hr != S_OK)
1904  {
1905  ERR("IMarshal::GetUnmarshalClass failed, 0x%08x\n", hr);
1906  goto cleanup;
1907  }
1908 
1909  /* FIXME: implement handler marshaling too */
1910  if (IsEqualCLSID(&marshaler_clsid, &CLSID_StdMarshal))
1911  {
1912  TRACE("Using standard marshaling\n");
1913  }
1914  else
1915  {
1916  OBJREF objref;
1917 
1918  TRACE("Using custom marshaling\n");
1919  objref.signature = OBJREF_SIGNATURE;
1920  objref.iid = *riid;
1921  objref.flags = OBJREF_CUSTOM;
1922  objref.u_objref.u_custom.clsid = marshaler_clsid;
1923  objref.u_objref.u_custom.cbExtension = 0;
1924  objref.u_objref.u_custom.size = 0;
1925  hr = IMarshal_GetMarshalSizeMax(pMarshal, riid, pUnk, dwDestContext,
1926  pvDestContext, mshlFlags,
1927  &objref.u_objref.u_custom.size);
1928  if (hr != S_OK)
1929  {
1930  ERR("Failed to get max size of marshal data, error 0x%08x\n", hr);
1931  goto cleanup;
1932  }
1933  /* write constant sized common header and OR_CUSTOM data into stream */
1934  hr = IStream_Write(pStream, &objref,
1935  FIELD_OFFSET(OBJREF, u_objref.u_custom.pData), NULL);
1936  if (hr != S_OK)
1937  {
1938  ERR("Failed to write OR_CUSTOM header to stream with 0x%08x\n", hr);
1939  goto cleanup;
1940  }
1941  }
1942 
1943  TRACE("Calling IMarshal::MarshalInterface\n");
1944  /* call helper object to do the actual marshaling */
1945  hr = IMarshal_MarshalInterface(pMarshal, pStream, riid, pUnk, dwDestContext,
1946  pvDestContext, mshlFlags);
1947 
1948  if (hr != S_OK)
1949  {
1950  ERR("Failed to marshal the interface %s, %x\n", debugstr_guid(riid), hr);
1951  goto cleanup;
1952  }
1953 
1954 cleanup:
1955  IMarshal_Release(pMarshal);
1956 
1957  TRACE("completed with hr 0x%08x\n", hr);
1958 
1959  return hr;
1960 }
1961 
1962 /***********************************************************************
1963  * CoUnmarshalInterface [OLE32.@]
1964  *
1965  * Unmarshals an object from a stream by creating a proxy to the remote
1966  * object, if necessary.
1967  *
1968  * PARAMS
1969  *
1970  * pStream [I] Stream containing the marshaled object.
1971  * riid [I] Interface identifier of the object to create a proxy to.
1972  * ppv [O] Address where proxy will be stored.
1973  *
1974  * RETURNS
1975  *
1976  * Success: S_OK.
1977  * Failure: HRESULT code.
1978  *
1979  * SEE ALSO
1980  * CoMarshalInterface().
1981  */
1983 {
1984  HRESULT hr;
1985  LPMARSHAL pMarshal;
1986  IID iid;
1987  IUnknown *object;
1988 
1989  TRACE("(%p, %s, %p)\n", pStream, debugstr_guid(riid), ppv);
1990 
1991  if (!pStream || !ppv)
1992  return E_INVALIDARG;
1993 
1994  hr = get_unmarshaler_from_stream(pStream, &pMarshal, &iid);
1995  if (hr == S_FALSE)
1996  {
1997  hr = std_unmarshal_interface(0, NULL, pStream, &iid, (void**)&object);
1998  if (hr != S_OK)
1999  ERR("StdMarshal UnmarshalInterface failed, 0x%08x\n", hr);
2000  }
2001  else if (hr == S_OK)
2002  {
2003  /* call the helper object to do the actual unmarshaling */
2004  hr = IMarshal_UnmarshalInterface(pMarshal, pStream, &iid, (LPVOID*)&object);
2005  IMarshal_Release(pMarshal);
2006  if (hr != S_OK)
2007  ERR("IMarshal::UnmarshalInterface failed, 0x%08x\n", hr);
2008  }
2009 
2010  if (hr == S_OK)
2011  {
2012  /* IID_NULL means use the interface ID of the marshaled object */
2013  if (!IsEqualIID(riid, &IID_NULL) && !IsEqualIID(riid, &iid))
2014  {
2015  TRACE("requested interface != marshalled interface, additional QI needed\n");
2016  hr = IUnknown_QueryInterface(object, riid, ppv);
2017  if (hr != S_OK)
2018  ERR("Couldn't query for interface %s, hr = 0x%08x\n",
2019  debugstr_guid(riid), hr);
2020  IUnknown_Release(object);
2021  }
2022  else
2023  {
2024  *ppv = object;
2025  }
2026  }
2027 
2028  TRACE("completed with hr 0x%x\n", hr);
2029 
2030  return hr;
2031 }
2032 
2033 /***********************************************************************
2034  * CoReleaseMarshalData [OLE32.@]
2035  *
2036  * Releases resources associated with an object that has been marshaled into
2037  * a stream.
2038  *
2039  * PARAMS
2040  *
2041  * pStream [I] The stream that the object has been marshaled into.
2042  *
2043  * RETURNS
2044  * Success: S_OK.
2045  * Failure: HRESULT error code.
2046  *
2047  * NOTES
2048  *
2049  * Call this function to release resources associated with a normal or
2050  * table-weak marshal that will not be unmarshaled, and all table-strong
2051  * marshals when they are no longer needed.
2052  *
2053  * SEE ALSO
2054  * CoMarshalInterface(), CoUnmarshalInterface().
2055  */
2057 {
2058  HRESULT hr;
2059  LPMARSHAL pMarshal;
2060 
2061  TRACE("(%p)\n", pStream);
2062 
2063  hr = get_unmarshaler_from_stream(pStream, &pMarshal, NULL);
2064  if (hr == S_FALSE)
2065  {
2066  hr = std_release_marshal_data(pStream);
2067  if (hr != S_OK)
2068  ERR("StdMarshal ReleaseMarshalData failed with error 0x%08x\n", hr);
2069  return hr;
2070  }
2071  if (hr != S_OK)
2072  return hr;
2073 
2074  /* call the helper object to do the releasing of marshal data */
2075  hr = IMarshal_ReleaseMarshalData(pMarshal, pStream);
2076  if (hr != S_OK)
2077  ERR("IMarshal::ReleaseMarshalData failed with error 0x%08x\n", hr);
2078 
2079  IMarshal_Release(pMarshal);
2080  return hr;
2081 }
2082 
2083 
2084 /***********************************************************************
2085  * CoMarshalInterThreadInterfaceInStream [OLE32.@]
2086  *
2087  * Marshal an interface across threads in the same process.
2088  *
2089  * PARAMS
2090  * riid [I] Identifier of the interface to be marshalled.
2091  * pUnk [I] Pointer to IUnknown-derived interface that will be marshalled.
2092  * ppStm [O] Pointer to IStream object that is created and then used to store the marshalled interface.
2093  *
2094  * RETURNS
2095  * Success: S_OK
2096  * Failure: E_OUTOFMEMORY and other COM error codes
2097  *
2098  * SEE ALSO
2099  * CoMarshalInterface(), CoUnmarshalInterface() and CoGetInterfaceAndReleaseStream()
2100  */
2102  REFIID riid, LPUNKNOWN pUnk, LPSTREAM * ppStm)
2103 {
2104  ULARGE_INTEGER xpos;
2106  HRESULT hres;
2107 
2108  TRACE("(%s, %p, %p)\n",debugstr_guid(riid), pUnk, ppStm);
2109 
2110  hres = CreateStreamOnHGlobal(NULL, TRUE, ppStm);
2111  if (FAILED(hres)) return hres;
2112  hres = CoMarshalInterface(*ppStm, riid, pUnk, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
2113 
2114  if (SUCCEEDED(hres))
2115  {
2116  memset(&seekto, 0, sizeof(seekto));
2117  IStream_Seek(*ppStm, seekto, STREAM_SEEK_SET, &xpos);
2118  }
2119  else
2120  {
2121  IStream_Release(*ppStm);
2122  *ppStm = NULL;
2123  }
2124 
2125  return hres;
2126 }
2127 
2128 /***********************************************************************
2129  * CoGetInterfaceAndReleaseStream [OLE32.@]
2130  *
2131  * Unmarshalls an interface from a stream and then releases the stream.
2132  *
2133  * PARAMS
2134  * pStm [I] Stream that contains the marshalled interface.
2135  * riid [I] Interface identifier of the object to unmarshall.
2136  * ppv [O] Address of pointer where the requested interface object will be stored.
2137  *
2138  * RETURNS
2139  * Success: S_OK
2140  * Failure: A COM error code
2141  *
2142  * SEE ALSO
2143  * CoMarshalInterThreadInterfaceInStream() and CoUnmarshalInterface()
2144  */
2146  LPVOID *ppv)
2147 {
2148  HRESULT hres;
2149 
2150  TRACE("(%p, %s, %p)\n", pStm, debugstr_guid(riid), ppv);
2151 
2152  if(!pStm) return E_INVALIDARG;
2153  hres = CoUnmarshalInterface(pStm, riid, ppv);
2154  IStream_Release(pStm);
2155  return hres;
2156 }
2157 
2158 static HRESULT WINAPI StdMarshalCF_QueryInterface(LPCLASSFACTORY iface,
2159  REFIID riid, LPVOID *ppv)
2160 {
2161  *ppv = NULL;
2163  {
2164  *ppv = iface;
2165  return S_OK;
2166  }
2167  return E_NOINTERFACE;
2168 }
2169 
2170 static ULONG WINAPI StdMarshalCF_AddRef(LPCLASSFACTORY iface)
2171 {
2172  return 2; /* non-heap based object */
2173 }
2174 
2175 static ULONG WINAPI StdMarshalCF_Release(LPCLASSFACTORY iface)
2176 {
2177  return 1; /* non-heap based object */
2178 }
2179 
2180 static HRESULT WINAPI StdMarshalCF_CreateInstance(LPCLASSFACTORY iface,
2182 {
2183  if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IMarshal))
2184  return StdMarshalImpl_Construct(riid, 0, NULL, ppv);
2185 
2186  FIXME("(%s), not supported.\n",debugstr_guid(riid));
2187  return E_NOINTERFACE;
2188 }
2189 
2190 static HRESULT WINAPI StdMarshalCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)
2191 {
2192  FIXME("(%d), stub!\n",fLock);
2193  return S_OK;
2194 }
2195 
2196 static const IClassFactoryVtbl StdMarshalCFVtbl =
2197 {
2203 };
2204 static const IClassFactoryVtbl *StdMarshalCF = &StdMarshalCFVtbl;
2205 
2207 {
2208  *ppv = &StdMarshalCF;
2209  return S_OK;
2210 }
2211 
2212 /***********************************************************************
2213  * CoMarshalHresult [OLE32.@]
2214  *
2215  * Marshals an HRESULT value into a stream.
2216  *
2217  * PARAMS
2218  * pStm [I] Stream that hresult will be marshalled into.
2219  * hresult [I] HRESULT to be marshalled.
2220  *
2221  * RETURNS
2222  * Success: S_OK
2223  * Failure: A COM error code
2224  *
2225  * SEE ALSO
2226  * CoUnmarshalHresult().
2227  */
2229 {
2230  return IStream_Write(pStm, &hresult, sizeof(hresult), NULL);
2231 }
2232 
2233 /***********************************************************************
2234  * CoUnmarshalHresult [OLE32.@]
2235  *
2236  * Unmarshals an HRESULT value from a stream.
2237  *
2238  * PARAMS
2239  * pStm [I] Stream that hresult will be unmarshalled from.
2240  * phresult [I] Pointer to HRESULT where the value will be unmarshalled to.
2241  *
2242  * RETURNS
2243  * Success: S_OK
2244  * Failure: A COM error code
2245  *
2246  * SEE ALSO
2247  * CoMarshalHresult().
2248  */
2250 {
2251  return IStream_Read(pStm, phresult, sizeof(*phresult), NULL);
2252 }
HRESULT WINAPI CoReleaseMarshalData(IStream *pStream)
Definition: marshal.c:2056
WINE_DEFAULT_DEBUG_CHANNEL(ole)
interface IMarshal * LPMARSHAL
Definition: objfwd.h:11
struct list entry
Definition: marshal.c:60
IMultiQI IMultiQI_iface
Definition: marshal.c:56
WCHAR OLECHAR
Definition: compat.h:1933
static HRESULT ifproxy_get_public_ref(struct ifproxy *This)
Definition: marshal.c:682
struct proxy_manager * parent
static ULONG WINAPI ProxyCliSec_AddRef(IClientSecurity *iface)
Definition: marshal.c:606
struct ifstub * stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *sb, REFIID iid, DWORD dest_context, void *dest_context_data, MSHLFLAGS flags) DECLSPEC_HIDDEN
Definition: stubmanager.c:70
HRESULT WINAPI CoUnmarshalInterface(IStream *pStream, REFIID riid, LPVOID *ppv)
Definition: marshal.c:1982
struct ifstub * stub_manager_find_ifstub(struct stub_manager *m, REFIID iid, MSHLFLAGS flags) DECLSPEC_HIDDEN
Definition: stubmanager.c:158
static void proxy_manager_set_context(struct proxy_manager *This, MSHCTX dest_context, void *dest_context_data)
Definition: marshal.c:875
ULONG flags
Definition: marshal.c:92
static HRESULT WINAPI ClientIdentity_QueryInterface(IMultiQI *iface, REFIID riid, void **ppv)
Definition: marshal.c:223
static HRESULT proxy_manager_query_local_interface(struct proxy_manager *This, REFIID riid, void **ppv)
Definition: marshal.c:933
int proxy
Definition: main.c:67
#define TRUE
Definition: types.h:120
static HRESULT WINAPI ProxyCliSec_SetBlanket(IClientSecurity *iface, IUnknown *pProxy, DWORD AuthnSvc, DWORD AuthzSvc, OLECHAR *pServerPrincName, DWORD AuthnLevel, DWORD ImpLevel, void *pAuthInfo, DWORD Capabilities)
Definition: marshal.c:650
#define CloseHandle
Definition: compat.h:398
HRESULT WINAPI CoMarshalHresult(LPSTREAM pStm, HRESULT hresult)
Definition: marshal.c:2228
#define E_NOINTERFACE
Definition: winerror.h:2364
HRESULT apartment_createwindowifneeded(struct apartment *apt)
Definition: compobj.c:1707
#define HRESULT_FROM_WIN32(x)
Definition: winerror.h:92
IPID ipid
Definition: marshal.c:96
#define OBJREF_SIGNATURE
Definition: marshal.c:77
VOID WINAPI CoTaskMemFree(LPVOID ptr)
Definition: ifs.c:422
DWORD dest_context
Definition: marshal.c:1245
#define SORFP_NOLIFETIMEMGMT
Definition: marshal.c:51
HRESULT apartment_disconnectproxies(struct apartment *apt)
Definition: marshal.c:1227
HRESULT hr
Definition: shlfolder.c:183
static HRESULT WINAPI ClientIdentity_QueryMultipleInterfaces(IMultiQI *iface, ULONG cMQIs, MULTI_QI *pMQIs)
Definition: marshal.c:254
static HRESULT apartment_getoxid(const struct apartment *apt, OXID *oxid)
static ULONG WINAPI StdMarshalCF_Release(LPCLASSFACTORY iface)
Definition: marshal.c:2175
BOOL stub_manager_notify_unmarshal(struct stub_manager *m, const IPID *ipid) DECLSPEC_HIDDEN
Definition: stubmanager.c:562
union tagOBJREF::@1614 u_objref
LPRPCPROXYBUFFER proxy
static HRESULT WINAPI StdMarshalImpl_QueryInterface(IMarshal *iface, REFIID riid, void **ppv)
Definition: marshal.c:1255
static const IMarshalVtbl StdMarshalVtbl
Definition: marshal.c:1621
CRITICAL_SECTION cs
Definition: marshal.c:66
STDOBJREF stdobjref
REFIID riid
Definition: precomp.h:44
struct list interfaces
Definition: marshal.c:64
#define DEBUG_SET_CRITSEC_NAME(cs, name)
IUnknown * iface
DWORD apartment_release(struct apartment *apt)
Definition: compobj.c:1175
static HRESULT get_unmarshaler_from_stream(IStream *stream, IMarshal **marshal, IID *iid)
Definition: marshal.c:1720
GUID iid
Definition: marshal.c:102
ULONG signature
Definition: marshal.c:100
static ULONG WINAPI StdMarshalCF_AddRef(LPCLASSFACTORY iface)
Definition: marshal.c:2170
static void proxy_manager_destroy(struct proxy_manager *This)
Definition: marshal.c:1156
MSHCTX dest_context
Definition: marshal.c:70
static HRESULT WINAPI StdMarshalImpl_GetUnmarshalClass(IMarshal *iface, REFIID riid, void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, CLSID *pCid)
Definition: marshal.c:1286
ULONG stub_manager_int_release(struct stub_manager *This) DECLSPEC_HIDDEN
Definition: stubmanager.c:311
uint8_t entry
Definition: isohybrid.c:63
void * dest_context_data
Definition: marshal.c:1246
#define WARN(fmt,...)
Definition: debug.h:111
static HRESULT proxy_manager_get_remunknown(struct proxy_manager *This, IRemUnknown **remunk)
Definition: marshal.c:1089
APARTMENT * apt
#define RPC_C_AUTHN_LEVEL_DEFAULT
Definition: rpcdce.h:145
static HRESULT WINAPI ProxyCliSec_QueryInterface(IClientSecurity *iface, REFIID riid, void **ppvObject)
Definition: marshal.c:600
HRESULT WINAPI CoGetInterfaceAndReleaseStream(LPSTREAM pStm, REFIID riid, LPVOID *ppv)
Definition: marshal.c:2145
REFIID LPVOID * ppv
Definition: atlbase.h:39
Definition: stubgen.c:11
static HRESULT WINAPI Proxy_UnmarshalInterface(IMarshal *iface, IStream *pStm, REFIID riid, void **ppv)
Definition: marshal.c:532
_Check_return_ _Out_ PULONG pulSize
Definition: winddi.h:2120
#define InterlockedCompareExchange
Definition: interlocked.h:104
const char * wine_dbgstr_guid(const GUID *guid)
#define assert(x)
Definition: debug.h:53
IMarshal IMarshal_iface
Definition: marshal.c:1243
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
HRESULT WINAPI CreateStreamOnHGlobal(HGLOBAL hGlobal, BOOL fDeleteOnRelease, LPSTREAM *ppstm)
static HRESULT WINAPI Proxy_QueryInterface(IMarshal *iface, REFIID riid, void **ppvObject)
Definition: marshal.c:365
interface IStream * LPSTREAM
Definition: objfwd.h:10
static HRESULT WINAPI Proxy_GetUnmarshalClass(IMarshal *iface, REFIID riid, void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, CLSID *pCid)
Definition: marshal.c:383
static HRESULT WINAPI StdMarshalImpl_UnmarshalInterface(IMarshal *iface, IStream *pStm, REFIID riid, void **ppv)
Definition: marshal.c:1508
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
Definition: features.h:417
Definition: send.c:47
#define CO_E_OBJNOTCONNECTED
Definition: winerror.h:2816
#define CO_E_NOTINITIALIZED
LONG refs
Definition: marshal.c:65
__WINE_SERVER_LIST_INLINE struct list * list_head(const struct list *list)
Definition: list.h:131
static HRESULT proxy_manager_construct(APARTMENT *apt, ULONG sorflags, OXID oxid, OID oid, const OXID_INFO *oxid_info, struct proxy_manager **proxy_manager)
Definition: marshal.c:794
__WINE_SERVER_LIST_INLINE void list_add_tail(struct list *list, struct list *elem)
Definition: list.h:102
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
static void dump_MSHLFLAGS(MSHLFLAGS flags)
Definition: marshal.c:1833
static const IClassFactoryVtbl * StdMarshalCF
Definition: marshal.c:2204
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
static ULONG WINAPI Proxy_Release(IMarshal *iface)
Definition: marshal.c:377
struct tagOBJREF OBJREF
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
_Must_inspect_result_ typedef _Out_ PHIDP_CAPS Capabilities
Definition: hidclass.h:103
_In_ HANDLE _In_ DWORD _In_ DWORD _Inout_opt_ LPOVERLAPPED _In_opt_ LPTRANSMIT_FILE_BUFFERS _In_ DWORD dwReserved
Definition: mswsock.h:90
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
void stub_manager_release_marshal_data(struct stub_manager *m, ULONG refs, const IPID *ipid, BOOL tableweak) DECLSPEC_HIDDEN
Definition: stubmanager.c:593
struct tagOBJREF::@1614::OR_CUSTOM u_custom
static const IClientSecurityVtbl ProxyCliSec_Vtbl
Definition: marshal.c:672
#define DEBUG_CLEAR_CRITSEC_NAME(cs)
static LPUNKNOWN
Definition: ndr_ole.c:49
LPVOID iface
BOOL stub_manager_is_table_marshaled(struct stub_manager *m, const IPID *ipid) DECLSPEC_HIDDEN
Definition: stubmanager.c:609
#define debugstr_w
Definition: kernel32.h:32
static HRESULT WINAPI StdMarshalCF_QueryInterface(LPCLASSFACTORY iface, REFIID riid, LPVOID *ppv)
Definition: marshal.c:2158
GLenum GLint ref
Definition: glext.h:6028
static void fill_std_objref(OBJREF *objref, const GUID *iid, STDOBJREF *std)
Definition: marshal.c:399
#define FIXME(fmt,...)
Definition: debug.h:110
struct _StdMarshalImpl StdMarshalImpl
static ULONG WINAPI StdMarshalImpl_AddRef(IMarshal *iface)
Definition: marshal.c:1269
STDOBJREF std
Definition: marshal.c:105
#define S_FALSE
Definition: winerror.h:2357
HRESULT WINAPI CoUnmarshalHresult(LPSTREAM pStm, HRESULT *phresult)
Definition: marshal.c:2249
#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
struct list proxies
ULONG stub_manager_ext_addref(struct stub_manager *m, ULONG refs, BOOL tableweak) DECLSPEC_HIDDEN
Definition: stubmanager.c:408
static HRESULT proxy_manager_create_ifproxy(struct proxy_manager *This, const STDOBJREF *stdobjref, REFIID riid, IRpcChannelBuffer *channel, struct ifproxy **iif_out)
Definition: marshal.c:972
static StdMarshalImpl * impl_from_StdMarshal(IMarshal *iface)
Definition: marshal.c:1249
HANDLE remoting_mutex
Definition: marshal.c:69
static HRESULT std_release_marshal_data(IStream *pStm)
Definition: marshal.c:1538
GLuint index
Definition: glext.h:6031
HRESULT WINAPI CoGetPSClsid(REFIID riid, CLSID *pclsid)
Definition: compobj.c:2599
#define debugstr_guid
Definition: kernel32.h:35
#define InterlockedExchangeAdd
Definition: interlocked.h:181
static struct proxy_manager * impl_from_IClientSecurity(IClientSecurity *iface)
Definition: marshal.c:84
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
HRESULT WINAPI DECLSPEC_HOTPATCH CoGetClassObject(REFCLSID rclsid, DWORD dwClsContext, COSERVERINFO *pServerInfo, REFIID iid, LPVOID *ppv)
Definition: compobj.c:3012
#define OBJREF_STANDARD
Definition: marshal.c:78
struct list entry
ULONG flags
Definition: marshal.c:101
static HRESULT WINAPI StdMarshalImpl_DisconnectObject(IMarshal *iface, DWORD dwReserved)
Definition: marshal.c:1615
__WINE_SERVER_LIST_INLINE void list_remove(struct list *elem)
Definition: list.h:108
static void ifproxy_disconnect(struct ifproxy *This)
Definition: marshal.c:763
static HRESULT WINAPI Proxy_ReleaseMarshalData(IMarshal *iface, IStream *pStm)
Definition: marshal.c:551
static ULONG WINAPI ProxyCliSec_Release(IClientSecurity *iface)
Definition: marshal.c:612
IRpcChannelBuffer * chan
#define TRACE(s)
Definition: solgame.cpp:4
OXID oxid
Definition: marshal.c:94
#define InterlockedExchangePointer(Target, Value)
Definition: dshow.h:45
static HRESULT unmarshal_object(const STDOBJREF *stdobjref, APARTMENT *apt, MSHCTX dest_context, void *dest_context_data, REFIID riid, const OXID_INFO *oxid_info, void **object)
Definition: marshal.c:1341
#define WAIT_OBJECT_0
Definition: winbase.h:387
HRESULT hres
Definition: protocol.c:465
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
OXID_INFO oxid_info
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
OXID_INFO oxid_info
Definition: marshal.c:62
LONG HRESULT
Definition: typedefs.h:77
static HRESULT get_marshaler(REFIID riid, IUnknown *pUnk, DWORD dwDestContext, void *pvDestContext, DWORD mshlFlags, LPMARSHAL *pMarshal)
Definition: marshal.c:1698
struct tagOBJREF::@1614::OR_STANDARD u_standard
const GUID IID_IUnknown
HRESULT RPC_RegisterInterface(REFIID riid) DECLSPEC_HIDDEN
Definition: rpc.c:1534
static HRESULT WINAPI ProxyCliSec_QueryBlanket(IClientSecurity *iface, IUnknown *pProxy, DWORD *pAuthnSvc, DWORD *pAuthzSvc, OLECHAR **ppServerPrincName, DWORD *pAuthnLevel, DWORD *pImpLevel, void **pAuthInfo, DWORD *pCapabilities)
Definition: marshal.c:618
static void ifproxy_destroy(struct ifproxy *This)
Definition: marshal.c:773
#define WINAPI
Definition: msvc.h:8
static HRESULT WINAPI StdMarshalImpl_GetMarshalSizeMax(IMarshal *iface, REFIID riid, void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, DWORD *pSize)
Definition: marshal.c:1295
unsigned long DWORD
Definition: ntddk_ex.h:95
GLenum GLenum GLenum GLenum mapping
Definition: glext.h:9031
static const IID IID_IRemUnknown
Definition: marshal.c:130
static HRESULT WINAPI Proxy_GetMarshalSizeMax(IMarshal *iface, REFIID riid, void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, DWORD *pSize)
Definition: marshal.c:391
static ULONG WINAPI ClientIdentity_AddRef(IMultiQI *iface)
Definition: marshal.c:237
#define RPC_E_DISCONNECTED
Definition: winerror.h:2484
static ULONG WINAPI Proxy_AddRef(IMarshal *iface)
Definition: marshal.c:371
#define WINE_CLSCTX_DONT_HOST
UINT64 OID
Definition: marshal.c:88
GLbitfield flags
Definition: glext.h:7161
BOOL WINAPI DECLSPEC_HOTPATCH ReleaseMutex(IN HANDLE hMutex)
Definition: synch.c:564
REFCLSID clsid
Definition: msctf.c:84
#define index(s, c)
Definition: various.h:29
#define seekto(pos, errstr)
Definition: mkdosfs.c:1613
#define IID_NULL
Definition: guiddef.h:93
#define InterlockedDecrement
Definition: armddk.h:52
Definition: parse.h:22
APARTMENT * apartment_get_current_or_mta(void)
Definition: compobj.c:745
static ULONG WINAPI ClientIdentity_Release(IMultiQI *iface)
Definition: marshal.c:244
#define NORMALEXTREFS
Definition: marshal.c:44
IRemUnknown * remunk
Definition: marshal.c:68
ULONG sorflags
Definition: marshal.c:67
Definition: _list.h:228
REFIID LPVOID * ppvObject
Definition: precomp.h:44
struct apartment * parent
Definition: marshal.c:59
static HRESULT StdMarshalImpl_Construct(REFIID, DWORD, void *, void **)
Definition: marshal.c:1634
static HRESULT proxy_manager_find_ifproxy(struct proxy_manager *This, REFIID riid, struct ifproxy **ifproxy_found)
Definition: marshal.c:1040
struct stub_manager * get_stub_manager(APARTMENT *apt, OID oid) DECLSPEC_HIDDEN
Definition: stubmanager.c:380
HRESULT WINAPI CoGetMarshalSizeMax(ULONG *pulSize, REFIID riid, IUnknown *pUnk, DWORD dwDestContext, void *pvDestContext, DWORD mshlFlags)
Definition: marshal.c:1801
const CLSID CLSID_StdMarshal
#define OBJREF_CUSTOM
Definition: marshal.c:79
void * dest_context_data
Definition: marshal.c:71
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv)
Definition: compobj.c:3234
#define ERR(fmt,...)
Definition: debug.h:109
APARTMENT * apartment_findfromoxid(OXID oxid, BOOL ref)
Definition: compobj.c:1279
void RPC_StartRemoting(struct apartment *apt) DECLSPEC_HIDDEN
Definition: rpc.c:1634
ULONG stub_manager_ext_release(struct stub_manager *m, ULONG refs, BOOL tableweak, BOOL last_unlock_releases) DECLSPEC_HIDDEN
Definition: stubmanager.c:439
HRESULT WINAPI CoMarshalInterThreadInterfaceInStream(REFIID riid, LPUNKNOWN pUnk, LPSTREAM *ppStm)
Definition: marshal.c:2101
#define S_OK
Definition: intsafe.h:59
IUnknown * object
#define InterlockedIncrement
Definition: armddk.h:53
const char cursor[]
Definition: icontest.c:13
HRESULT WINAPI CoGetStandardMarshal(REFIID riid, IUnknown *pUnk, DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags, LPMARSHAL *ppMarshal)
Definition: marshal.c:1677
UINT64 OXID
Definition: marshal.c:87
static HRESULT ifproxy_release_public_refs(struct ifproxy *This)
Definition: marshal.c:719
static const IClassFactoryVtbl StdMarshalCFVtbl
Definition: marshal.c:2196
#define E_NOTIMPL
Definition: ddrawi.h:99
static HRESULT get_facbuf_for_iid(REFIID riid, IPSFactoryBuffer **facbuf)
Definition: marshal.c:109
HANDLE WINAPI DECLSPEC_HOTPATCH CreateMutexW(IN LPSECURITY_ATTRIBUTES lpMutexAttributes OPTIONAL, IN BOOL bInitialOwner, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:522
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
HRESULT MARSHAL_GetStandardMarshalCF(LPVOID *ppv)
Definition: marshal.c:2206
static HRESULT WINAPI StdMarshalImpl_MarshalInterface(IMarshal *iface, IStream *pStm, REFIID riid, void *pv, DWORD dest_context, void *dest_context_data, DWORD mshlflags)
Definition: marshal.c:1304
#define STG_E_READFAULT
Definition: winerror.h:2576
IMarshal IMarshal_iface
Definition: marshal.c:57
static ULONG WINAPI StdMarshalImpl_Release(IMarshal *iface)
Definition: marshal.c:1276
#define E_UNEXPECTED
Definition: winerror.h:2456
OXID oxid
Definition: marshal.c:61
IClientSecurity IClientSecurity_iface
Definition: marshal.c:58
GLuint res
Definition: glext.h:9613
__WINE_SERVER_LIST_INLINE void list_init(struct list *list)
Definition: list.h:149
HRESULT RPC_CreateClientChannel(const OXID *oxid, const IPID *ipid, const OXID_INFO *oxid_info, const IID *iid, DWORD dest_context, void *dest_context_data, IRpcChannelBuffer **chan, APARTMENT *apt) DECLSPEC_HIDDEN
Definition: rpc.c:1099
unsigned int ULONG
Definition: retypes.h:1
static const IMarshalVtbl ProxyMarshal_Vtbl
Definition: marshal.c:587
static __inline const char * wine_dbgstr_longlong(ULONGLONG ll)
Definition: compat.h:41
HRESULT RPC_ResolveOxid(OXID oxid, OXID_INFO *oxid_info) DECLSPEC_HIDDEN
Definition: rpc.c:1613
char * cleanup(char *str)
Definition: wpickclick.c:99
ULONG cPublicRefs
Definition: marshal.c:93
static BOOL find_proxy_manager(APARTMENT *apt, OXID oxid, OID oid, struct proxy_manager **proxy_found)
Definition: marshal.c:1201
static HRESULT std_unmarshal_interface(MSHCTX dest_context, void *dest_context_data, IStream *pStm, REFIID riid, void **ppv)
Definition: marshal.c:1410
static HRESULT WINAPI Proxy_MarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags)
Definition: marshal.c:410
#define RPC_E_INVALID_OBJREF
Definition: winerror.h:2505
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
struct stub_manager * get_stub_manager_from_object(APARTMENT *apt, IUnknown *object, BOOL alloc) DECLSPEC_HIDDEN
Definition: stubmanager.c:337
static void proxy_manager_disconnect(struct proxy_manager *This)
Definition: marshal.c:1061
#define LIST_ENTRY(type)
Definition: queue.h:175
HRESULT marshal_object(APARTMENT *apt, STDOBJREF *stdobjref, REFIID riid, IUnknown *object, DWORD dest_context, void *dest_context_data, MSHLFLAGS mshlflags)
Definition: marshal.c:122
HRESULT WINAPI CoMarshalInterface(IStream *pStream, REFIID riid, IUnknown *pUnk, DWORD dwDestContext, void *pvDestContext, DWORD mshlFlags)
Definition: marshal.c:1877
#define E_POINTER
Definition: winerror.h:2365
#define INFINITE
Definition: serial.h:102
#define RPC_C_IMP_LEVEL_DEFAULT
Definition: rpcdce.h:173
CRITICAL_SECTION cs
static HRESULT WINAPI StdMarshalImpl_ReleaseMarshalData(IMarshal *iface, IStream *pStm)
Definition: marshal.c:1584
const GUID IID_IClassFactory
static struct proxy_manager * impl_from_IMarshal(IMarshal *iface)
Definition: marshal.c:79
#define memset(x, y, z)
Definition: compat.h:39
signed int * PLONG
Definition: retypes.h:5
static HRESULT WINAPI StdMarshalCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)
Definition: marshal.c:2190
#define IsEqualCLSID(rclsid1, rclsid2)
Definition: guiddef.h:91
static HRESULT WINAPI StdMarshalCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv)
Definition: marshal.c:2180
static void *static void *static LPDIRECTPLAY IUnknown * pUnk
Definition: dplayx.c:30
static HRESULT WINAPI ProxyCliSec_CopyProxy(IClientSecurity *iface, IUnknown *pProxy, IUnknown **ppCopy)
Definition: marshal.c:664
static REFIID
Definition: marshal.c:67
#define HeapFree(x, y, z)
Definition: compat.h:394
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:90
void * object
Definition: jmemsys.h:48
#define SUCCEEDED(hr)
Definition: intsafe.h:57
static struct proxy_manager * impl_from_IMultiQI(IMultiQI *iface)
Definition: marshal.c:74
static const IMultiQIVtbl ClientIdentity_Vtbl
Definition: marshal.c:355
#define SORFP_TABLEWEAK
Definition: marshal.c:48
static HRESULT WINAPI Proxy_DisconnectObject(IMarshal *iface, DWORD dwReserved)
Definition: marshal.c:569