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