dbghelp: Use local declarations of r_debug and link_map structs.
[wine.git] / dlls / ole32 / ftmarshal.c
blob851810df42a811d8c589f752a621f404fa806649
1 /*
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
21 #include <stdlib.h>
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <assert.h>
27 #define COBJMACROS
29 #include "windef.h"
30 #include "winbase.h"
31 #include "objbase.h"
33 #include "wine/debug.h"
35 #include "compobj_private.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(ole);
39 typedef struct _FTMarshalImpl {
40 IUnknown IUnknown_inner;
41 IMarshal IMarshal_iface;
42 IUnknown *outer_unk;
43 LONG ref;
44 } FTMarshalImpl;
46 static inline FTMarshalImpl *impl_from_IUnknown(IUnknown *iface)
48 return CONTAINING_RECORD(iface, FTMarshalImpl, IUnknown_inner);
51 static inline FTMarshalImpl *impl_from_IMarshal( IMarshal *iface )
53 return CONTAINING_RECORD(iface, FTMarshalImpl, IMarshal_iface);
56 /* inner IUnknown to handle aggregation */
57 static HRESULT WINAPI
58 IiFTMUnknown_fnQueryInterface (IUnknown * iface, REFIID riid, LPVOID * ppv)
61 FTMarshalImpl *This = impl_from_IUnknown(iface);
63 TRACE ("\n");
64 *ppv = NULL;
66 if (IsEqualIID (&IID_IUnknown, riid))
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;
74 IUnknown_AddRef ((IUnknown *) * ppv);
75 return S_OK;
78 static ULONG WINAPI IiFTMUnknown_fnAddRef (IUnknown * iface)
81 FTMarshalImpl *This = impl_from_IUnknown(iface);
83 TRACE ("\n");
84 return InterlockedIncrement (&This->ref);
87 static ULONG WINAPI IiFTMUnknown_fnRelease (IUnknown * iface)
90 FTMarshalImpl *This = impl_from_IUnknown(iface);
92 TRACE ("\n");
93 if (InterlockedDecrement (&This->ref))
94 return This->ref;
95 HeapFree (GetProcessHeap (), 0, This);
96 return 0;
99 static const IUnknownVtbl iunkvt =
101 IiFTMUnknown_fnQueryInterface,
102 IiFTMUnknown_fnAddRef,
103 IiFTMUnknown_fnRelease
106 static HRESULT WINAPI
107 FTMarshalImpl_QueryInterface (LPMARSHAL iface, REFIID riid, LPVOID * ppv)
110 FTMarshalImpl *This = impl_from_IMarshal(iface);
112 TRACE ("(%p)->(%s,%p)\n", This, debugstr_guid (riid), ppv);
113 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
116 static ULONG WINAPI
117 FTMarshalImpl_AddRef (LPMARSHAL iface)
120 FTMarshalImpl *This = impl_from_IMarshal(iface);
122 TRACE ("\n");
123 return IUnknown_AddRef(This->outer_unk);
126 static ULONG WINAPI
127 FTMarshalImpl_Release (LPMARSHAL iface)
130 FTMarshalImpl *This = impl_from_IMarshal(iface);
132 TRACE ("\n");
133 return IUnknown_Release(This->outer_unk);
136 static HRESULT WINAPI
137 FTMarshalImpl_GetUnmarshalClass (LPMARSHAL iface, REFIID riid, void *pv, DWORD dwDestContext,
138 void *pvDestContext, DWORD mshlflags, CLSID * pCid)
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)
143 *pCid = CLSID_InProcFreeMarshaler;
144 else
145 *pCid = CLSID_StdMarshal;
146 return S_OK;
149 static HRESULT WINAPI
150 FTMarshalImpl_GetMarshalSizeMax (LPMARSHAL iface, REFIID riid, void *pv, DWORD dwDestContext,
151 void *pvDestContext, DWORD mshlflags, DWORD * pSize)
154 IMarshal *pMarshal = NULL;
155 HRESULT hres;
157 TRACE("(%s, %p, 0x%x, %p, 0x%x, %p)\n", debugstr_guid(riid), pv,
158 dwDestContext, pvDestContext, mshlflags, pSize);
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;
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;
174 static HRESULT WINAPI
175 FTMarshalImpl_MarshalInterface (LPMARSHAL iface, IStream * pStm, REFIID riid, void *pv,
176 DWORD dwDestContext, void *pvDestContext, DWORD mshlflags)
179 IMarshal *pMarshal = NULL;
180 HRESULT hres;
182 TRACE("(%p, %s, %p, 0x%x, %p, 0x%x)\n", pStm, debugstr_guid(riid), pv,
183 dwDestContext, pvDestContext, mshlflags);
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 };
192 hres = IUnknown_QueryInterface((IUnknown *)pv, riid, &object);
193 if (FAILED(hres))
194 return hres;
196 /* don't hold a reference to table-weak marshaled interfaces */
197 if (mshlflags & MSHLFLAGS_TABLEWEAK)
198 IUnknown_Release((IUnknown *)object);
200 hres = IStream_Write (pStm, &mshlflags, sizeof (mshlflags), NULL);
201 if (hres != S_OK) return STG_E_MEDIUMFULL;
203 hres = IStream_Write (pStm, &object, sizeof (object), NULL);
204 if (hres != S_OK) return STG_E_MEDIUMFULL;
206 if (sizeof(object) == sizeof(DWORD))
208 hres = IStream_Write (pStm, &constant, sizeof (constant), NULL);
209 if (hres != S_OK) return STG_E_MEDIUMFULL;
212 hres = IStream_Write (pStm, &unknown_guid, sizeof (unknown_guid), NULL);
213 if (hres != S_OK) return STG_E_MEDIUMFULL;
215 return S_OK;
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;
225 static HRESULT WINAPI
226 FTMarshalImpl_UnmarshalInterface (LPMARSHAL iface, IStream * pStm, REFIID riid, void **ppv)
228 DWORD mshlflags;
229 IUnknown *object;
230 DWORD constant;
231 GUID unknown_guid;
232 HRESULT hres;
234 TRACE ("(%p, %s, %p)\n", pStm, debugstr_guid(riid), ppv);
236 hres = IStream_Read (pStm, &mshlflags, sizeof (mshlflags), NULL);
237 if (hres != S_OK) return STG_E_READFAULT;
239 hres = IStream_Read (pStm, &object, sizeof (object), NULL);
240 if (hres != S_OK) return STG_E_READFAULT;
242 if (sizeof(object) == sizeof(DWORD))
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);
250 hres = IStream_Read (pStm, &unknown_guid, sizeof (unknown_guid), NULL);
251 if (hres != S_OK) return STG_E_READFAULT;
253 hres = IUnknown_QueryInterface(object, riid, ppv);
254 if (!(mshlflags & (MSHLFLAGS_TABLEWEAK|MSHLFLAGS_TABLESTRONG)))
255 IUnknown_Release(object);
256 return hres;
259 static HRESULT WINAPI FTMarshalImpl_ReleaseMarshalData (LPMARSHAL iface, IStream * pStm)
261 DWORD mshlflags;
262 IUnknown *object;
263 DWORD constant;
264 GUID unknown_guid;
265 HRESULT hres;
267 TRACE ("(%p)\n", pStm);
269 hres = IStream_Read (pStm, &mshlflags, sizeof (mshlflags), NULL);
270 if (hres != S_OK) return STG_E_READFAULT;
272 hres = IStream_Read (pStm, &object, sizeof (object), NULL);
273 if (hres != S_OK) return STG_E_READFAULT;
275 if (sizeof(object) == sizeof(DWORD))
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);
283 hres = IStream_Read (pStm, &unknown_guid, sizeof (unknown_guid), NULL);
284 if (hres != S_OK) return STG_E_READFAULT;
286 IUnknown_Release(object);
287 return S_OK;
290 static HRESULT WINAPI FTMarshalImpl_DisconnectObject (LPMARSHAL iface, DWORD dwReserved)
292 TRACE ("()\n");
293 /* nothing to do */
294 return S_OK;
297 static const IMarshalVtbl ftmvtbl =
299 FTMarshalImpl_QueryInterface,
300 FTMarshalImpl_AddRef,
301 FTMarshalImpl_Release,
302 FTMarshalImpl_GetUnmarshalClass,
303 FTMarshalImpl_GetMarshalSizeMax,
304 FTMarshalImpl_MarshalInterface,
305 FTMarshalImpl_UnmarshalInterface,
306 FTMarshalImpl_ReleaseMarshalData,
307 FTMarshalImpl_DisconnectObject
310 /***********************************************************************
311 * CoCreateFreeThreadedMarshaler [OLE32.@]
313 * Creates a free-threaded marshaler.
315 * PARAMS
316 * punkOuter [I] Optional. Outer unknown.
317 * ppunkMarshal [O] On return, the inner unknown of the created free-threaded marshaler.
319 * RETURNS
320 * Success: S_OK
321 * Failure: E_OUTOFMEMORY if no memory available to create object.
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.
331 HRESULT WINAPI CoCreateFreeThreadedMarshaler (LPUNKNOWN punkOuter, LPUNKNOWN * ppunkMarshal)
334 FTMarshalImpl *ftm;
336 TRACE ("(%p %p)\n", punkOuter, ppunkMarshal);
338 ftm = HeapAlloc (GetProcessHeap (), 0, sizeof (FTMarshalImpl));
339 if (!ftm)
340 return E_OUTOFMEMORY;
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;
347 *ppunkMarshal = &ftm->IUnknown_inner;
348 return S_OK;
351 static HRESULT WINAPI FTMarshalCF_QueryInterface(LPCLASSFACTORY iface,
352 REFIID riid, LPVOID *ppv)
354 *ppv = NULL;
355 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory))
357 *ppv = iface;
358 IClassFactory_AddRef(iface);
359 return S_OK;
361 return E_NOINTERFACE;
364 static ULONG WINAPI FTMarshalCF_AddRef(LPCLASSFACTORY iface)
366 return 2; /* non-heap based object */
369 static ULONG WINAPI FTMarshalCF_Release(LPCLASSFACTORY iface)
371 return 1; /* non-heap based object */
374 static HRESULT WINAPI FTMarshalCF_CreateInstance(LPCLASSFACTORY iface,
375 LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv)
377 IUnknown *pUnknown;
378 HRESULT hr;
380 TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv);
382 *ppv = NULL;
384 hr = CoCreateFreeThreadedMarshaler(pUnk, &pUnknown);
386 if (SUCCEEDED(hr))
388 hr = IUnknown_QueryInterface(pUnknown, riid, ppv);
389 IUnknown_Release(pUnknown);
392 return hr;
395 static HRESULT WINAPI FTMarshalCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)
397 FIXME("(%d), stub!\n",fLock);
398 return S_OK;
401 static const IClassFactoryVtbl FTMarshalCFVtbl =
403 FTMarshalCF_QueryInterface,
404 FTMarshalCF_AddRef,
405 FTMarshalCF_Release,
406 FTMarshalCF_CreateInstance,
407 FTMarshalCF_LockServer
409 static const IClassFactoryVtbl *FTMarshalCF = &FTMarshalCFVtbl;
411 HRESULT FTMarshalCF_Create(REFIID riid, LPVOID *ppv)
413 return IClassFactory_QueryInterface((IClassFactory *)&FTMarshalCF, riid, ppv);