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 typedef struct _FTMarshalImpl {
42 const IUnknownVtbl *lpVtbl;
44 const IMarshalVtbl *lpvtblFTM;
49 #define _IFTMUnknown_(This)(IUnknown*)&(This->lpVtbl)
50 #define _IFTMarshal_(This) (IMarshal*)&(This->lpvtblFTM)
52 static inline FTMarshalImpl *impl_from_IMarshal( IMarshal *iface )
54 return (FTMarshalImpl *)((char*)iface - FIELD_OFFSET(FTMarshalImpl, lpvtblFTM));
57 /* inner IUnknown to handle aggregation */
59 IiFTMUnknown_fnQueryInterface (IUnknown * iface, REFIID riid, LPVOID * ppv)
62 FTMarshalImpl *This = (FTMarshalImpl *)iface;
67 if (IsEqualIID (&IID_IUnknown, riid))
68 *ppv = _IFTMUnknown_ (This);
69 else if (IsEqualIID (&IID_IMarshal, riid))
70 *ppv = _IFTMarshal_ (This);
72 FIXME ("No interface for %s.\n", debugstr_guid (riid));
75 IUnknown_AddRef ((IUnknown *) * ppv);
79 static ULONG WINAPI IiFTMUnknown_fnAddRef (IUnknown * iface)
82 FTMarshalImpl *This = (FTMarshalImpl *)iface;
85 return InterlockedIncrement (&This->ref);
88 static ULONG WINAPI IiFTMUnknown_fnRelease (IUnknown * iface)
91 FTMarshalImpl *This = (FTMarshalImpl *)iface;
94 if (InterlockedDecrement (&This->ref))
96 HeapFree (GetProcessHeap (), 0, This);
100 static const IUnknownVtbl iunkvt =
102 IiFTMUnknown_fnQueryInterface,
103 IiFTMUnknown_fnAddRef,
104 IiFTMUnknown_fnRelease
107 static HRESULT WINAPI
108 FTMarshalImpl_QueryInterface (LPMARSHAL iface, REFIID riid, LPVOID * ppv)
111 FTMarshalImpl *This = impl_from_IMarshal(iface);
113 TRACE ("(%p)->(\n\tIID:\t%s,%p)\n", This, debugstr_guid (riid), ppv);
114 return IUnknown_QueryInterface (This->pUnkOuter, riid, ppv);
118 FTMarshalImpl_AddRef (LPMARSHAL iface)
121 FTMarshalImpl *This = impl_from_IMarshal(iface);
124 return IUnknown_AddRef (This->pUnkOuter);
128 FTMarshalImpl_Release (LPMARSHAL iface)
131 FTMarshalImpl *This = impl_from_IMarshal(iface);
134 return IUnknown_Release (This->pUnkOuter);
137 static HRESULT WINAPI
138 FTMarshalImpl_GetUnmarshalClass (LPMARSHAL iface, REFIID riid, void *pv, DWORD dwDestContext,
139 void *pvDestContext, DWORD mshlflags, CLSID * pCid)
141 FIXME ("(), stub!\n");
145 static HRESULT WINAPI
146 FTMarshalImpl_GetMarshalSizeMax (LPMARSHAL iface, REFIID riid, void *pv, DWORD dwDestContext,
147 void *pvDestContext, DWORD mshlflags, DWORD * pSize)
150 IMarshal *pMarshal = NULL;
153 FTMarshalImpl *This = impl_from_IMarshal(iface);
155 FIXME ("(), stub!\n");
157 /* if the marshalling happens inside the same process the interface pointer is
158 copied between the apartments */
159 if (dwDestContext == MSHCTX_INPROC || dwDestContext == MSHCTX_CROSSCTX) {
160 *pSize = sizeof (This);
164 /* use the standard marshaller to handle all other cases */
165 CoGetStandardMarshal (riid, pv, dwDestContext, pvDestContext, mshlflags, &pMarshal);
166 hres = IMarshal_GetMarshalSizeMax (pMarshal, riid, pv, dwDestContext, pvDestContext, mshlflags, pSize);
167 IMarshal_Release (pMarshal);
171 static HRESULT WINAPI
172 FTMarshalImpl_MarshalInterface (LPMARSHAL iface, IStream * pStm, REFIID riid, void *pv,
173 DWORD dwDestContext, void *pvDestContext, DWORD mshlflags)
176 IMarshal *pMarshal = NULL;
178 DWORD magic = 0x57dfd54d /* MEOW */;
180 TRACE("(%p, %s, %p, 0x%lx, %p, 0x%lx)\n", pStm, debugstr_guid(riid), pv,
181 dwDestContext, pvDestContext, mshlflags);
183 /* if the marshalling happens inside the same process the interface pointer is
184 copied between the apartments */
185 if (dwDestContext == MSHCTX_INPROC || dwDestContext == MSHCTX_CROSSCTX) {
188 GUID unknown_guid = { 0 };
190 hres = IUnknown_QueryInterface((IUnknown *)pv, riid, &object);
194 /* don't hold a reference to table-weak marshaled interfaces */
195 if (mshlflags & MSHLFLAGS_TABLEWEAK)
196 IUnknown_Release((IUnknown *)object);
198 hres = IStream_Write (pStm, &mshlflags, sizeof (mshlflags), NULL);
199 if (hres != S_OK) return STG_E_MEDIUMFULL;
201 hres = IStream_Write (pStm, &object, sizeof (object), NULL);
202 if (hres != S_OK) return STG_E_MEDIUMFULL;
204 hres = IStream_Write (pStm, &constant, sizeof (constant), NULL);
205 if (hres != S_OK) return STG_E_MEDIUMFULL;
207 hres = IStream_Write (pStm, &unknown_guid, sizeof (unknown_guid), NULL);
208 if (hres != S_OK) return STG_E_MEDIUMFULL;
213 /* FIXME: this isn't exactly corret. it looks like the standard marshaler
214 * for native writes all of the OBJREF data into the stream, so we should
215 * really rely on it to write this constant for us. however, we need a
216 * constant to differentiate the outofproc data from the inproc data */
217 hres = IStream_Write (pStm, &magic, sizeof (magic), NULL);
218 if (hres != S_OK) return STG_E_MEDIUMFULL;
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);
227 static HRESULT WINAPI
228 FTMarshalImpl_UnmarshalInterface (LPMARSHAL iface, IStream * pStm, REFIID riid, void **ppv)
233 TRACE ("(%p, %s, %p)\n", pStm, debugstr_guid(riid), ppv);
235 hres = IStream_Read (pStm, &mshlflags, sizeof (mshlflags), NULL);
236 if (hres != S_OK) return STG_E_READFAULT;
238 if (mshlflags == 0x57dfd54d /* MEOW */) {
241 hres = CoCreateInstance (&CLSID_DfMarshal, NULL, CLSCTX_INPROC, &IID_IMarshal, (void **)&pMarshal);
242 if (FAILED(hres)) return hres;
244 hres = IMarshal_UnmarshalInterface (pMarshal, pStm, riid, ppv);
245 IMarshal_Release (pMarshal);
253 hres = IStream_Read (pStm, &object, sizeof (object), NULL);
254 if (hres != S_OK) return STG_E_READFAULT;
256 hres = IStream_Read (pStm, &constant, sizeof (constant), NULL);
257 if (hres != S_OK) return STG_E_READFAULT;
259 FIXME("constant is 0x%lx instead of 0\n", constant);
261 hres = IStream_Read (pStm, &unknown_guid, sizeof (unknown_guid), NULL);
262 if (hres != S_OK) return STG_E_READFAULT;
264 hres = IUnknown_QueryInterface(object, riid, ppv);
265 if (!(mshlflags & MSHLFLAGS_TABLEWEAK))
266 IUnknown_Release(object);
271 static HRESULT WINAPI FTMarshalImpl_ReleaseMarshalData (LPMARSHAL iface, IStream * pStm)
273 FIXME ("(), stub!\n");
277 static HRESULT WINAPI FTMarshalImpl_DisconnectObject (LPMARSHAL iface, DWORD dwReserved)
279 FIXME ("(), stub!\n");
283 static const IMarshalVtbl ftmvtbl =
285 FTMarshalImpl_QueryInterface,
286 FTMarshalImpl_AddRef,
287 FTMarshalImpl_Release,
288 FTMarshalImpl_GetUnmarshalClass,
289 FTMarshalImpl_GetMarshalSizeMax,
290 FTMarshalImpl_MarshalInterface,
291 FTMarshalImpl_UnmarshalInterface,
292 FTMarshalImpl_ReleaseMarshalData,
293 FTMarshalImpl_DisconnectObject
296 /***********************************************************************
297 * CoCreateFreeThreadedMarshaler [OLE32.@]
300 HRESULT WINAPI CoCreateFreeThreadedMarshaler (LPUNKNOWN punkOuter, LPUNKNOWN * ppunkMarshal)
305 TRACE ("(%p %p)\n", punkOuter, ppunkMarshal);
307 ftm = HeapAlloc (GetProcessHeap (), 0, sizeof (FTMarshalImpl));
309 return E_OUTOFMEMORY;
311 ftm->lpVtbl = &iunkvt;
312 ftm->lpvtblFTM = &ftmvtbl;
314 ftm->pUnkOuter = punkOuter ? punkOuter : _IFTMUnknown_(ftm);
316 *ppunkMarshal = _IFTMUnknown_ (ftm);