ReactOS  0.4.14-dev-98-gb0d4763
ftmarshal.c
Go to the documentation of this file.
1 /*
2  * free threaded marshaller
3  *
4  * Copyright 2002 Juergen Schmied
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #include "config.h"
22 
23 #include <stdlib.h>
24 #include <stdarg.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <assert.h>
28 
29 #define COBJMACROS
30 
31 #include "windef.h"
32 #include "winbase.h"
33 #include "objbase.h"
34 
35 #include "wine/debug.h"
36 
37 #include "compobj_private.h"
38 
40 
41 typedef struct _FTMarshalImpl {
47 
49 {
50  return CONTAINING_RECORD(iface, FTMarshalImpl, IUnknown_inner);
51 }
52 
53 static inline FTMarshalImpl *impl_from_IMarshal( IMarshal *iface )
54 {
55  return CONTAINING_RECORD(iface, FTMarshalImpl, IMarshal_iface);
56 }
57 
58 /* inner IUnknown to handle aggregation */
59 static HRESULT WINAPI
61 {
62 
64 
65  TRACE ("\n");
66  *ppv = NULL;
67 
69  *ppv = &This->IUnknown_inner;
70  else if (IsEqualIID (&IID_IMarshal, riid))
71  *ppv = &This->IMarshal_iface;
72  else {
73  FIXME ("No interface for %s.\n", debugstr_guid (riid));
74  return E_NOINTERFACE;
75  }
76  IUnknown_AddRef ((IUnknown *) * ppv);
77  return S_OK;
78 }
79 
81 {
82 
84 
85  TRACE ("\n");
86  return InterlockedIncrement (&This->ref);
87 }
88 
90 {
91 
93 
94  TRACE ("\n");
95  if (InterlockedDecrement (&This->ref))
96  return This->ref;
97  HeapFree (GetProcessHeap (), 0, This);
98  return 0;
99 }
100 
101 static const IUnknownVtbl iunkvt =
102 {
106 };
107 
108 static HRESULT WINAPI
110 {
111 
113 
114  TRACE ("(%p)->(%s,%p)\n", This, debugstr_guid (riid), ppv);
115  return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
116 }
117 
118 static ULONG WINAPI
120 {
121 
123 
124  TRACE ("\n");
125  return IUnknown_AddRef(This->outer_unk);
126 }
127 
128 static ULONG WINAPI
130 {
131 
133 
134  TRACE ("\n");
135  return IUnknown_Release(This->outer_unk);
136 }
137 
138 static HRESULT WINAPI
139 FTMarshalImpl_GetUnmarshalClass (LPMARSHAL iface, REFIID riid, void *pv, DWORD dwDestContext,
140  void *pvDestContext, DWORD mshlflags, CLSID * pCid)
141 {
142  TRACE("(%s, %p, 0x%x, %p, 0x%x, %p)\n", debugstr_guid(riid), pv,
143  dwDestContext, pvDestContext, mshlflags, pCid);
144  if (dwDestContext == MSHCTX_INPROC || dwDestContext == MSHCTX_CROSSCTX)
146  else
147  *pCid = CLSID_StdMarshal;
148  return S_OK;
149 }
150 
151 static HRESULT WINAPI
152 FTMarshalImpl_GetMarshalSizeMax (LPMARSHAL iface, REFIID riid, void *pv, DWORD dwDestContext,
153  void *pvDestContext, DWORD mshlflags, DWORD * pSize)
154 {
155 
156  IMarshal *pMarshal = NULL;
157  HRESULT hres;
158 
159  TRACE("(%s, %p, 0x%x, %p, 0x%x, %p)\n", debugstr_guid(riid), pv,
160  dwDestContext, pvDestContext, mshlflags, pSize);
161 
162  /* if the marshalling happens inside the same process the interface pointer is
163  copied between the apartments */
164  if (dwDestContext == MSHCTX_INPROC || dwDestContext == MSHCTX_CROSSCTX) {
165  *pSize = sizeof (mshlflags) + sizeof (pv) + sizeof (DWORD) + sizeof (GUID);
166  return S_OK;
167  }
168 
169  /* use the standard marshaller to handle all other cases */
170  CoGetStandardMarshal (riid, pv, dwDestContext, pvDestContext, mshlflags, &pMarshal);
171  hres = IMarshal_GetMarshalSizeMax (pMarshal, riid, pv, dwDestContext, pvDestContext, mshlflags, pSize);
172  IMarshal_Release (pMarshal);
173  return hres;
174 }
175 
176 static HRESULT WINAPI
178  DWORD dwDestContext, void *pvDestContext, DWORD mshlflags)
179 {
180 
181  IMarshal *pMarshal = NULL;
182  HRESULT hres;
183 
184  TRACE("(%p, %s, %p, 0x%x, %p, 0x%x)\n", pStm, debugstr_guid(riid), pv,
185  dwDestContext, pvDestContext, mshlflags);
186 
187  /* if the marshalling happens inside the same process the interface pointer is
188  copied between the apartments */
189  if (dwDestContext == MSHCTX_INPROC || dwDestContext == MSHCTX_CROSSCTX) {
190  void *object;
191  DWORD constant = 0;
192  GUID unknown_guid = { 0 };
193 
194  hres = IUnknown_QueryInterface((IUnknown *)pv, riid, &object);
195  if (FAILED(hres))
196  return hres;
197 
198  /* don't hold a reference to table-weak marshaled interfaces */
199  if (mshlflags & MSHLFLAGS_TABLEWEAK)
200  IUnknown_Release((IUnknown *)object);
201 
202  hres = IStream_Write (pStm, &mshlflags, sizeof (mshlflags), NULL);
203  if (hres != S_OK) return STG_E_MEDIUMFULL;
204 
205  hres = IStream_Write (pStm, &object, sizeof (object), NULL);
206  if (hres != S_OK) return STG_E_MEDIUMFULL;
207 
208  if (sizeof(object) == sizeof(DWORD))
209  {
210  hres = IStream_Write (pStm, &constant, sizeof (constant), NULL);
211  if (hres != S_OK) return STG_E_MEDIUMFULL;
212  }
213 
214  hres = IStream_Write (pStm, &unknown_guid, sizeof (unknown_guid), NULL);
215  if (hres != S_OK) return STG_E_MEDIUMFULL;
216 
217  return S_OK;
218  }
219 
220  /* use the standard marshaler to handle all other cases */
221  CoGetStandardMarshal (riid, pv, dwDestContext, pvDestContext, mshlflags, &pMarshal);
222  hres = IMarshal_MarshalInterface (pMarshal, pStm, riid, pv, dwDestContext, pvDestContext, mshlflags);
223  IMarshal_Release (pMarshal);
224  return hres;
225 }
226 
227 static HRESULT WINAPI
229 {
230  DWORD mshlflags;
231  IUnknown *object;
232  DWORD constant;
233  GUID unknown_guid;
234  HRESULT hres;
235 
236  TRACE ("(%p, %s, %p)\n", pStm, debugstr_guid(riid), ppv);
237 
238  hres = IStream_Read (pStm, &mshlflags, sizeof (mshlflags), NULL);
239  if (hres != S_OK) return STG_E_READFAULT;
240 
241  hres = IStream_Read (pStm, &object, sizeof (object), NULL);
242  if (hres != S_OK) return STG_E_READFAULT;
243 
244  if (sizeof(object) == sizeof(DWORD))
245  {
246  hres = IStream_Read (pStm, &constant, sizeof (constant), NULL);
247  if (hres != S_OK) return STG_E_READFAULT;
248  if (constant != 0)
249  FIXME("constant is 0x%x instead of 0\n", constant);
250  }
251 
252  hres = IStream_Read (pStm, &unknown_guid, sizeof (unknown_guid), NULL);
253  if (hres != S_OK) return STG_E_READFAULT;
254 
255  hres = IUnknown_QueryInterface(object, riid, ppv);
256  if (!(mshlflags & (MSHLFLAGS_TABLEWEAK|MSHLFLAGS_TABLESTRONG)))
257  IUnknown_Release(object);
258  return hres;
259 }
260 
262 {
263  DWORD mshlflags;
264  IUnknown *object;
265  DWORD constant;
266  GUID unknown_guid;
267  HRESULT hres;
268 
269  TRACE ("(%p)\n", pStm);
270 
271  hres = IStream_Read (pStm, &mshlflags, sizeof (mshlflags), NULL);
272  if (hres != S_OK) return STG_E_READFAULT;
273 
274  hres = IStream_Read (pStm, &object, sizeof (object), NULL);
275  if (hres != S_OK) return STG_E_READFAULT;
276 
277  if (sizeof(object) == sizeof(DWORD))
278  {
279  hres = IStream_Read (pStm, &constant, sizeof (constant), NULL);
280  if (hres != S_OK) return STG_E_READFAULT;
281  if (constant != 0)
282  FIXME("constant is 0x%x instead of 0\n", constant);
283  }
284 
285  hres = IStream_Read (pStm, &unknown_guid, sizeof (unknown_guid), NULL);
286  if (hres != S_OK) return STG_E_READFAULT;
287 
288  IUnknown_Release(object);
289  return S_OK;
290 }
291 
293 {
294  TRACE ("()\n");
295  /* nothing to do */
296  return S_OK;
297 }
298 
299 static const IMarshalVtbl ftmvtbl =
300 {
310 };
311 
312 /***********************************************************************
313  * CoCreateFreeThreadedMarshaler [OLE32.@]
314  *
315  * Creates a free-threaded marshaler.
316  *
317  * PARAMS
318  * punkOuter [I] Optional. Outer unknown.
319  * ppunkMarshal [O] On return, the inner unknown of the created free-threaded marshaler.
320  *
321  * RETURNS
322  * Success: S_OK
323  * Failure: E_OUTOFMEMORY if no memory available to create object.
324  *
325  * NOTES
326  * Objects that ensure their state is maintained consistent when used by
327  * multiple threads and reference no single-threaded objects are known as
328  * free-threaded. The free-threaded marshaler enables these objects to be
329  * efficiently marshaled within the same process, by not creating proxies
330  * (as they aren't needed for the object to be safely used), whilst still
331  * allowing the object to be used in inter-process and inter-machine contexts.
332  */
334 {
335 
336  FTMarshalImpl *ftm;
337 
338  TRACE ("(%p %p)\n", punkOuter, ppunkMarshal);
339 
340  ftm = HeapAlloc (GetProcessHeap (), 0, sizeof (FTMarshalImpl));
341  if (!ftm)
342  return E_OUTOFMEMORY;
343 
344  ftm->IUnknown_inner.lpVtbl = &iunkvt;
345  ftm->IMarshal_iface.lpVtbl = &ftmvtbl;
346  ftm->ref = 1;
347  ftm->outer_unk = punkOuter ? punkOuter : &ftm->IUnknown_inner;
348 
349  *ppunkMarshal = &ftm->IUnknown_inner;
350  return S_OK;
351 }
352 
353 static HRESULT WINAPI FTMarshalCF_QueryInterface(LPCLASSFACTORY iface,
354  REFIID riid, LPVOID *ppv)
355 {
356  *ppv = NULL;
358  {
359  *ppv = iface;
360  IClassFactory_AddRef(iface);
361  return S_OK;
362  }
363  return E_NOINTERFACE;
364 }
365 
366 static ULONG WINAPI FTMarshalCF_AddRef(LPCLASSFACTORY iface)
367 {
368  return 2; /* non-heap based object */
369 }
370 
371 static ULONG WINAPI FTMarshalCF_Release(LPCLASSFACTORY iface)
372 {
373  return 1; /* non-heap based object */
374 }
375 
376 static HRESULT WINAPI FTMarshalCF_CreateInstance(LPCLASSFACTORY iface,
378 {
380  HRESULT hr;
381 
382  TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv);
383 
384  *ppv = NULL;
385 
387 
388  if (SUCCEEDED(hr))
389  {
390  hr = IUnknown_QueryInterface(pUnknown, riid, ppv);
391  IUnknown_Release(pUnknown);
392  }
393 
394  return hr;
395 }
396 
397 static HRESULT WINAPI FTMarshalCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)
398 {
399  FIXME("(%d), stub!\n",fLock);
400  return S_OK;
401 }
402 
403 static const IClassFactoryVtbl FTMarshalCFVtbl =
404 {
410 };
411 static const IClassFactoryVtbl *FTMarshalCF = &FTMarshalCFVtbl;
412 
414 {
415  return IClassFactory_QueryInterface((IClassFactory *)&FTMarshalCF, riid, ppv);
416 }
interface IMarshal * LPMARSHAL
Definition: objfwd.h:11
#define REFIID
Definition: guiddef.h:118
static ULONG WINAPI FTMarshalCF_Release(LPCLASSFACTORY iface)
Definition: ftmarshal.c:371
#define E_NOINTERFACE
Definition: winerror.h:2364
static ULONG WINAPI IiFTMUnknown_fnAddRef(IUnknown *iface)
Definition: ftmarshal.c:80
HRESULT hr
Definition: shlfolder.c:183
WINE_DEFAULT_DEBUG_CHANNEL(ole)
static FTMarshalImpl * impl_from_IMarshal(IMarshal *iface)
Definition: ftmarshal.c:53
static HRESULT WINAPI FTMarshalImpl_UnmarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, void **ppv)
Definition: ftmarshal.c:228
static HRESULT WINAPI FTMarshalCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)
Definition: ftmarshal.c:397
REFIID riid
Definition: precomp.h:44
REFIID LPVOID * ppv
Definition: atlbase.h:39
IUnknown * outer_unk
Definition: ftmarshal.c:44
#define STG_E_MEDIUMFULL
Definition: winerror.h:2581
const CLSID CLSID_InProcFreeMarshaler
static HRESULT WINAPI FTMarshalImpl_GetUnmarshalClass(LPMARSHAL iface, REFIID riid, void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, CLSID *pCid)
Definition: ftmarshal.c:139
#define DWORD
Definition: nt_native.h:44
IMarshal IMarshal_iface
Definition: ftmarshal.c:43
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
_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
static ULONG WINAPI FTMarshalImpl_Release(LPMARSHAL iface)
Definition: ftmarshal.c:129
static LPUNKNOWN
Definition: ndr_ole.c:49
#define FIXME(fmt,...)
Definition: debug.h:110
smooth NULL
Definition: ftsmooth.c:416
#define debugstr_guid
Definition: kernel32.h:35
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
static ULONG WINAPI FTMarshalCF_AddRef(LPCLASSFACTORY iface)
Definition: ftmarshal.c:366
static HRESULT WINAPI FTMarshalImpl_GetMarshalSizeMax(LPMARSHAL iface, REFIID riid, void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, DWORD *pSize)
Definition: ftmarshal.c:152
static FTMarshalImpl * impl_from_IUnknown(IUnknown *iface)
Definition: ftmarshal.c:48
_In_ PUNKNOWN pUnknown
Definition: drmk.h:76
HRESULT FTMarshalCF_Create(REFIID riid, LPVOID *ppv)
Definition: ftmarshal.c:413
#define TRACE(s)
Definition: solgame.cpp:4
HRESULT hres
Definition: protocol.c:465
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
static const IClassFactoryVtbl FTMarshalCFVtbl
Definition: ftmarshal.c:403
LONG HRESULT
Definition: typedefs.h:77
static HRESULT WINAPI FTMarshalImpl_ReleaseMarshalData(LPMARSHAL iface, IStream *pStm)
Definition: ftmarshal.c:261
const GUID IID_IUnknown
#define WINAPI
Definition: msvc.h:8
unsigned long DWORD
Definition: ntddk_ex.h:95
static HRESULT WINAPI FTMarshalImpl_DisconnectObject(LPMARSHAL iface, DWORD dwReserved)
Definition: ftmarshal.c:292
static const IUnknownVtbl iunkvt
Definition: ftmarshal.c:101
#define InterlockedDecrement
Definition: armddk.h:52
const CLSID CLSID_StdMarshal
#define S_OK
Definition: intsafe.h:59
IUnknown IUnknown_inner
Definition: ftmarshal.c:42
#define InterlockedIncrement
Definition: armddk.h:53
HRESULT WINAPI CoGetStandardMarshal(REFIID riid, IUnknown *pUnk, DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags, LPMARSHAL *ppMarshal)
Definition: marshal.c:1677
struct _FTMarshalImpl FTMarshalImpl
static HRESULT WINAPI FTMarshalCF_QueryInterface(LPCLASSFACTORY iface, REFIID riid, LPVOID *ppv)
Definition: ftmarshal.c:353
#define STG_E_READFAULT
Definition: winerror.h:2576
static ULONG WINAPI FTMarshalImpl_AddRef(LPMARSHAL iface)
Definition: ftmarshal.c:119
static ULONG WINAPI IiFTMUnknown_fnRelease(IUnknown *iface)
Definition: ftmarshal.c:89
static const IMarshalVtbl ftmvtbl
Definition: ftmarshal.c:299
static const IClassFactoryVtbl * FTMarshalCF
Definition: ftmarshal.c:411
static HRESULT WINAPI FTMarshalCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv)
Definition: ftmarshal.c:376
static HRESULT WINAPI FTMarshalImpl_QueryInterface(LPMARSHAL iface, REFIID riid, LPVOID *ppv)
Definition: ftmarshal.c:109
unsigned int ULONG
Definition: retypes.h:1
static HRESULT WINAPI FTMarshalImpl_MarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags)
Definition: ftmarshal.c:177
const GUID IID_IClassFactory
HRESULT WINAPI CoCreateFreeThreadedMarshaler(LPUNKNOWN punkOuter, LPUNKNOWN *ppunkMarshal)
Definition: ftmarshal.c:333
static void *static void *static LPDIRECTPLAY IUnknown * pUnk
Definition: dplayx.c:30
static HRESULT WINAPI IiFTMUnknown_fnQueryInterface(IUnknown *iface, REFIID riid, LPVOID *ppv)
Definition: ftmarshal.c:60
#define HeapFree(x, y, z)
Definition: compat.h:394
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
void * object
Definition: jmemsys.h:48
#define SUCCEEDED(hr)
Definition: intsafe.h:57