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