2 * free threaded marshaller
4 * Copyright 2002 Juergen Schmied
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.
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.
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
35 #include "wine/debug.h"
37 #include "compobj_private.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(ole);
41 const CLSID CLSID_InProcFreeMarshaler = { 0x33A, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46} };
43 typedef struct _FTMarshalImpl {
44 const IUnknownVtbl *lpVtbl;
46 const IMarshalVtbl *lpvtblFTM;
51 #define _IFTMUnknown_(This)(IUnknown*)&(This->lpVtbl)
52 #define _IFTMarshal_(This) (IMarshal*)&(This->lpvtblFTM)
54 static inline FTMarshalImpl *impl_from_IMarshal( IMarshal *iface )
56 return (FTMarshalImpl *)((char*)iface - FIELD_OFFSET(FTMarshalImpl, lpvtblFTM));
59 /* inner IUnknown to handle aggregation */
61 IiFTMUnknown_fnQueryInterface (IUnknown * iface, REFIID riid, LPVOID * ppv)
64 FTMarshalImpl *This = (FTMarshalImpl *)iface;
69 if (IsEqualIID (&IID_IUnknown, riid))
70 *ppv = _IFTMUnknown_ (This);
71 else if (IsEqualIID (&IID_IMarshal, riid))
72 *ppv = _IFTMarshal_ (This);
74 FIXME ("No interface for %s.\n", debugstr_guid (riid));
77 IUnknown_AddRef ((IUnknown *) * ppv);
81 static ULONG WINAPI IiFTMUnknown_fnAddRef (IUnknown * iface)
84 FTMarshalImpl *This = (FTMarshalImpl *)iface;
87 return InterlockedIncrement (&This->ref);
90 static ULONG WINAPI IiFTMUnknown_fnRelease (IUnknown * iface)
93 FTMarshalImpl *This = (FTMarshalImpl *)iface;
96 if (InterlockedDecrement (&This->ref))
98 HeapFree (GetProcessHeap (), 0, This);
102 static const IUnknownVtbl iunkvt =
104 IiFTMUnknown_fnQueryInterface,
105 IiFTMUnknown_fnAddRef,
106 IiFTMUnknown_fnRelease
109 static HRESULT WINAPI
110 FTMarshalImpl_QueryInterface (LPMARSHAL iface, REFIID riid, LPVOID * ppv)
113 FTMarshalImpl *This = impl_from_IMarshal(iface);
115 TRACE ("(%p)->(\n\tIID:\t%s,%p)\n", This, debugstr_guid (riid), ppv);
116 return IUnknown_QueryInterface (This->pUnkOuter, riid, ppv);
120 FTMarshalImpl_AddRef (LPMARSHAL iface)
123 FTMarshalImpl *This = impl_from_IMarshal(iface);
126 return IUnknown_AddRef (This->pUnkOuter);
130 FTMarshalImpl_Release (LPMARSHAL iface)
133 FTMarshalImpl *This = impl_from_IMarshal(iface);
136 return IUnknown_Release (This->pUnkOuter);
139 static HRESULT WINAPI
140 FTMarshalImpl_GetUnmarshalClass (LPMARSHAL iface, REFIID riid, void *pv, DWORD dwDestContext,
141 void *pvDestContext, DWORD mshlflags, CLSID * pCid)
143 TRACE("(%s, %p, 0x%lx, %p, 0x%lx, %p)\n", debugstr_guid(riid), pv,
144 dwDestContext, pvDestContext, mshlflags, pCid);
145 if (dwDestContext == MSHCTX_INPROC || dwDestContext == MSHCTX_CROSSCTX)
146 memcpy(pCid, &CLSID_InProcFreeMarshaler, sizeof(CLSID_InProcFreeMarshaler));
148 memcpy(pCid, &CLSID_DfMarshal, sizeof(CLSID_InProcFreeMarshaler));
152 static HRESULT WINAPI
153 FTMarshalImpl_GetMarshalSizeMax (LPMARSHAL iface, REFIID riid, void *pv, DWORD dwDestContext,
154 void *pvDestContext, DWORD mshlflags, DWORD * pSize)
157 IMarshal *pMarshal = NULL;
160 FTMarshalImpl *This = impl_from_IMarshal(iface);
162 FIXME ("(), stub!\n");
164 /* if the marshalling happens inside the same process the interface pointer is
165 copied between the apartments */
166 if (dwDestContext == MSHCTX_INPROC || dwDestContext == MSHCTX_CROSSCTX) {
167 *pSize = sizeof (This);
171 /* use the standard marshaller to handle all other cases */
172 CoGetStandardMarshal (riid, pv, dwDestContext, pvDestContext, mshlflags, &pMarshal);
173 hres = IMarshal_GetMarshalSizeMax (pMarshal, riid, pv, dwDestContext, pvDestContext, mshlflags, pSize);
174 IMarshal_Release (pMarshal);
178 static HRESULT WINAPI
179 FTMarshalImpl_MarshalInterface (LPMARSHAL iface, IStream * pStm, REFIID riid, void *pv,
180 DWORD dwDestContext, void *pvDestContext, DWORD mshlflags)
183 IMarshal *pMarshal = NULL;
186 TRACE("(%p, %s, %p, 0x%lx, %p, 0x%lx)\n", pStm, debugstr_guid(riid), pv,
187 dwDestContext, pvDestContext, mshlflags);
189 /* if the marshalling happens inside the same process the interface pointer is
190 copied between the apartments */
191 if (dwDestContext == MSHCTX_INPROC || dwDestContext == MSHCTX_CROSSCTX) {
194 GUID unknown_guid = { 0 };
196 hres = IUnknown_QueryInterface((IUnknown *)pv, riid, &object);
200 /* don't hold a reference to table-weak marshaled interfaces */
201 if (mshlflags & MSHLFLAGS_TABLEWEAK)
202 IUnknown_Release((IUnknown *)object);
204 hres = IStream_Write (pStm, &mshlflags, sizeof (mshlflags), NULL);
205 if (hres != S_OK) return STG_E_MEDIUMFULL;
207 hres = IStream_Write (pStm, &object, sizeof (object), NULL);
208 if (hres != S_OK) return STG_E_MEDIUMFULL;
210 hres = IStream_Write (pStm, &constant, sizeof (constant), NULL);
211 if (hres != S_OK) return STG_E_MEDIUMFULL;
213 hres = IStream_Write (pStm, &unknown_guid, sizeof (unknown_guid), NULL);
214 if (hres != S_OK) return STG_E_MEDIUMFULL;
219 /* use the standard marshaler to handle all other cases */
220 CoGetStandardMarshal (riid, pv, dwDestContext, pvDestContext, mshlflags, &pMarshal);
221 hres = IMarshal_MarshalInterface (pMarshal, pStm, riid, pv, dwDestContext, pvDestContext, mshlflags);
222 IMarshal_Release (pMarshal);
226 static HRESULT WINAPI
227 FTMarshalImpl_UnmarshalInterface (LPMARSHAL iface, IStream * pStm, REFIID riid, void **ppv)
235 TRACE ("(%p, %s, %p)\n", pStm, debugstr_guid(riid), ppv);
237 hres = IStream_Read (pStm, &mshlflags, sizeof (mshlflags), NULL);
238 if (hres != S_OK) return STG_E_READFAULT;
240 hres = IStream_Read (pStm, &object, sizeof (object), NULL);
241 if (hres != S_OK) return STG_E_READFAULT;
243 hres = IStream_Read (pStm, &constant, sizeof (constant), NULL);
244 if (hres != S_OK) return STG_E_READFAULT;
246 FIXME("constant is 0x%lx instead of 0\n", constant);
248 hres = IStream_Read (pStm, &unknown_guid, sizeof (unknown_guid), NULL);
249 if (hres != S_OK) return STG_E_READFAULT;
251 hres = IUnknown_QueryInterface(object, riid, ppv);
252 if (!(mshlflags & (MSHLFLAGS_TABLEWEAK|MSHLFLAGS_TABLESTRONG)))
253 IUnknown_Release(object);
257 static HRESULT WINAPI FTMarshalImpl_ReleaseMarshalData (LPMARSHAL iface, IStream * pStm)
265 TRACE ("(%p)\n", pStm);
267 hres = IStream_Read (pStm, &mshlflags, sizeof (mshlflags), NULL);
268 if (hres != S_OK) return STG_E_READFAULT;
270 hres = IStream_Read (pStm, &object, sizeof (object), NULL);
271 if (hres != S_OK) return STG_E_READFAULT;
273 hres = IStream_Read (pStm, &constant, sizeof (constant), NULL);
274 if (hres != S_OK) return STG_E_READFAULT;
276 FIXME("constant is 0x%lx instead of 0\n", constant);
278 hres = IStream_Read (pStm, &unknown_guid, sizeof (unknown_guid), NULL);
279 if (hres != S_OK) return STG_E_READFAULT;
281 IUnknown_Release(object);
285 static HRESULT WINAPI FTMarshalImpl_DisconnectObject (LPMARSHAL iface, DWORD dwReserved)
292 static const IMarshalVtbl ftmvtbl =
294 FTMarshalImpl_QueryInterface,
295 FTMarshalImpl_AddRef,
296 FTMarshalImpl_Release,
297 FTMarshalImpl_GetUnmarshalClass,
298 FTMarshalImpl_GetMarshalSizeMax,
299 FTMarshalImpl_MarshalInterface,
300 FTMarshalImpl_UnmarshalInterface,
301 FTMarshalImpl_ReleaseMarshalData,
302 FTMarshalImpl_DisconnectObject
305 /***********************************************************************
306 * CoCreateFreeThreadedMarshaler [OLE32.@]
309 HRESULT WINAPI CoCreateFreeThreadedMarshaler (LPUNKNOWN punkOuter, LPUNKNOWN * ppunkMarshal)
314 TRACE ("(%p %p)\n", punkOuter, ppunkMarshal);
316 ftm = HeapAlloc (GetProcessHeap (), 0, sizeof (FTMarshalImpl));
318 return E_OUTOFMEMORY;
320 ftm->lpVtbl = &iunkvt;
321 ftm->lpvtblFTM = &ftmvtbl;
323 ftm->pUnkOuter = punkOuter ? punkOuter : _IFTMUnknown_(ftm);
325 *ppunkMarshal = _IFTMUnknown_ (ftm);
329 static HRESULT WINAPI FTMarshalCF_QueryInterface(LPCLASSFACTORY iface,
330 REFIID riid, LPVOID *ppv)
333 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory))
336 IUnknown_AddRef(iface);
339 return E_NOINTERFACE;
342 static ULONG WINAPI FTMarshalCF_AddRef(LPCLASSFACTORY iface)
344 return 2; /* non-heap based object */
347 static ULONG WINAPI FTMarshalCF_Release(LPCLASSFACTORY iface)
349 return 1; /* non-heap based object */
352 static HRESULT WINAPI FTMarshalCF_CreateInstance(LPCLASSFACTORY iface,
353 LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv)
358 TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv);
362 hr = CoCreateFreeThreadedMarshaler(pUnk, &pUnknown);
366 hr = IUnknown_QueryInterface(pUnknown, riid, ppv);
367 IUnknown_Release(pUnknown);
373 static HRESULT WINAPI FTMarshalCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)
375 FIXME("(%d), stub!\n",fLock);
379 static const IClassFactoryVtbl FTMarshalCFVtbl =
381 FTMarshalCF_QueryInterface,
384 FTMarshalCF_CreateInstance,
385 FTMarshalCF_LockServer
387 static const IClassFactoryVtbl *FTMarshalCF = &FTMarshalCFVtbl;
389 HRESULT FTMarshalCF_Create(REFIID riid, LPVOID *ppv)
391 return IClassFactory_QueryInterface((IClassFactory *)&FTMarshalCF, riid, ppv);