mshtml: Added beginning OnDataAvailable implementation.
[wine] / dlls / ole32 / ftmarshal.c
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
39 WINE_DEFAULT_DEBUG_CHANNEL(ole);
40
41 const CLSID CLSID_InProcFreeMarshaler = { 0x33A, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46} };
42
43 typedef struct _FTMarshalImpl {
44         const IUnknownVtbl *lpVtbl;
45         LONG ref;
46         const IMarshalVtbl *lpvtblFTM;
47
48         IUnknown *pUnkOuter;
49 } FTMarshalImpl;
50
51 #define _IFTMUnknown_(This)(IUnknown*)&(This->lpVtbl)
52 #define _IFTMarshal_(This) (IMarshal*)&(This->lpvtblFTM)
53
54 static inline FTMarshalImpl *impl_from_IMarshal( IMarshal *iface )
55 {
56     return (FTMarshalImpl *)((char*)iface - FIELD_OFFSET(FTMarshalImpl, lpvtblFTM));
57 }
58
59 /* inner IUnknown to handle aggregation */
60 static HRESULT WINAPI
61 IiFTMUnknown_fnQueryInterface (IUnknown * iface, REFIID riid, LPVOID * ppv)
62 {
63
64     FTMarshalImpl *This = (FTMarshalImpl *)iface;
65
66     TRACE ("\n");
67     *ppv = NULL;
68
69     if (IsEqualIID (&IID_IUnknown, riid))
70         *ppv = _IFTMUnknown_ (This);
71     else if (IsEqualIID (&IID_IMarshal, riid))
72         *ppv = _IFTMarshal_ (This);
73     else {
74         FIXME ("No interface for %s.\n", debugstr_guid (riid));
75         return E_NOINTERFACE;
76     }
77     IUnknown_AddRef ((IUnknown *) * ppv);
78     return S_OK;
79 }
80
81 static ULONG WINAPI IiFTMUnknown_fnAddRef (IUnknown * iface)
82 {
83
84     FTMarshalImpl *This = (FTMarshalImpl *)iface;
85
86     TRACE ("\n");
87     return InterlockedIncrement (&This->ref);
88 }
89
90 static ULONG WINAPI IiFTMUnknown_fnRelease (IUnknown * iface)
91 {
92
93     FTMarshalImpl *This = (FTMarshalImpl *)iface;
94
95     TRACE ("\n");
96     if (InterlockedDecrement (&This->ref))
97         return This->ref;
98     HeapFree (GetProcessHeap (), 0, This);
99     return 0;
100 }
101
102 static const IUnknownVtbl iunkvt =
103 {
104         IiFTMUnknown_fnQueryInterface,
105         IiFTMUnknown_fnAddRef,
106         IiFTMUnknown_fnRelease
107 };
108
109 static HRESULT WINAPI
110 FTMarshalImpl_QueryInterface (LPMARSHAL iface, REFIID riid, LPVOID * ppv)
111 {
112
113     FTMarshalImpl *This = impl_from_IMarshal(iface);
114
115     TRACE ("(%p)->(\n\tIID:\t%s,%p)\n", This, debugstr_guid (riid), ppv);
116     return IUnknown_QueryInterface (This->pUnkOuter, riid, ppv);
117 }
118
119 static ULONG WINAPI
120 FTMarshalImpl_AddRef (LPMARSHAL iface)
121 {
122
123     FTMarshalImpl *This = impl_from_IMarshal(iface);
124
125     TRACE ("\n");
126     return IUnknown_AddRef (This->pUnkOuter);
127 }
128
129 static ULONG WINAPI
130 FTMarshalImpl_Release (LPMARSHAL iface)
131 {
132
133     FTMarshalImpl *This = impl_from_IMarshal(iface);
134
135     TRACE ("\n");
136     return IUnknown_Release (This->pUnkOuter);
137 }
138
139 static HRESULT WINAPI
140 FTMarshalImpl_GetUnmarshalClass (LPMARSHAL iface, REFIID riid, void *pv, DWORD dwDestContext,
141                                                 void *pvDestContext, DWORD mshlflags, CLSID * pCid)
142 {
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));
147     else
148         memcpy(pCid, &CLSID_DfMarshal, sizeof(CLSID_InProcFreeMarshaler));
149     return S_OK;
150 }
151
152 static HRESULT WINAPI
153 FTMarshalImpl_GetMarshalSizeMax (LPMARSHAL iface, REFIID riid, void *pv, DWORD dwDestContext,
154                                                 void *pvDestContext, DWORD mshlflags, DWORD * pSize)
155 {
156
157     IMarshal *pMarshal = NULL;
158     HRESULT hres;
159
160     FTMarshalImpl *This = impl_from_IMarshal(iface);
161
162     FIXME ("(), stub!\n");
163
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);
168         return S_OK;
169     }
170
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);
175     return hres;
176 }
177
178 static HRESULT WINAPI
179 FTMarshalImpl_MarshalInterface (LPMARSHAL iface, IStream * pStm, REFIID riid, void *pv,
180                                DWORD dwDestContext, void *pvDestContext, DWORD mshlflags)
181 {
182
183     IMarshal *pMarshal = NULL;
184     HRESULT hres;
185
186     TRACE("(%p, %s, %p, 0x%lx, %p, 0x%lx)\n", pStm, debugstr_guid(riid), pv,
187         dwDestContext, pvDestContext, mshlflags);
188
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) {
192         void *object;
193         DWORD constant = 0;
194         GUID unknown_guid = { 0 };
195
196         hres = IUnknown_QueryInterface((IUnknown *)pv, riid, &object);
197         if (FAILED(hres))
198             return hres;
199
200         /* don't hold a reference to table-weak marshaled interfaces */
201         if (mshlflags & MSHLFLAGS_TABLEWEAK)
202             IUnknown_Release((IUnknown *)object);
203
204         hres = IStream_Write (pStm, &mshlflags, sizeof (mshlflags), NULL);
205         if (hres != S_OK) return STG_E_MEDIUMFULL;
206
207         hres = IStream_Write (pStm, &object, sizeof (object), NULL);
208         if (hres != S_OK) return STG_E_MEDIUMFULL;
209
210         hres = IStream_Write (pStm, &constant, sizeof (constant), NULL);
211         if (hres != S_OK) return STG_E_MEDIUMFULL;
212
213         hres = IStream_Write (pStm, &unknown_guid, sizeof (unknown_guid), NULL);
214         if (hres != S_OK) return STG_E_MEDIUMFULL;
215
216         return S_OK;
217     }
218
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);
223     return hres;
224 }
225
226 static HRESULT WINAPI
227 FTMarshalImpl_UnmarshalInterface (LPMARSHAL iface, IStream * pStm, REFIID riid, void **ppv)
228 {
229     DWORD mshlflags;
230     IUnknown *object;
231     DWORD constant;
232     GUID unknown_guid;
233     HRESULT hres;
234
235     TRACE ("(%p, %s, %p)\n", pStm, debugstr_guid(riid), ppv);
236
237     hres = IStream_Read (pStm, &mshlflags, sizeof (mshlflags), NULL);
238     if (hres != S_OK) return STG_E_READFAULT;
239
240     hres = IStream_Read (pStm, &object, sizeof (object), NULL);
241     if (hres != S_OK) return STG_E_READFAULT;
242
243     hres = IStream_Read (pStm, &constant, sizeof (constant), NULL);
244     if (hres != S_OK) return STG_E_READFAULT;
245     if (constant != 0)
246         FIXME("constant is 0x%lx instead of 0\n", constant);
247
248     hres = IStream_Read (pStm, &unknown_guid, sizeof (unknown_guid), NULL);
249     if (hres != S_OK) return STG_E_READFAULT;
250
251     hres = IUnknown_QueryInterface(object, riid, ppv);
252     if (!(mshlflags & (MSHLFLAGS_TABLEWEAK|MSHLFLAGS_TABLESTRONG)))
253         IUnknown_Release(object);
254     return hres;
255 }
256
257 static HRESULT WINAPI FTMarshalImpl_ReleaseMarshalData (LPMARSHAL iface, IStream * pStm)
258 {
259     DWORD mshlflags;
260     IUnknown *object;
261     DWORD constant;
262     GUID unknown_guid;
263     HRESULT hres;
264
265     TRACE ("(%p)\n", pStm);
266
267     hres = IStream_Read (pStm, &mshlflags, sizeof (mshlflags), NULL);
268     if (hres != S_OK) return STG_E_READFAULT;
269
270     hres = IStream_Read (pStm, &object, sizeof (object), NULL);
271     if (hres != S_OK) return STG_E_READFAULT;
272
273     hres = IStream_Read (pStm, &constant, sizeof (constant), NULL);
274     if (hres != S_OK) return STG_E_READFAULT;
275     if (constant != 0)
276         FIXME("constant is 0x%lx instead of 0\n", constant);
277
278     hres = IStream_Read (pStm, &unknown_guid, sizeof (unknown_guid), NULL);
279     if (hres != S_OK) return STG_E_READFAULT;
280
281     IUnknown_Release(object);
282     return S_OK;
283 }
284
285 static HRESULT WINAPI FTMarshalImpl_DisconnectObject (LPMARSHAL iface, DWORD dwReserved)
286 {
287     TRACE ("()\n");
288     /* nothing to do */
289     return S_OK;
290 }
291
292 static const IMarshalVtbl ftmvtbl =
293 {
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
303 };
304
305 /***********************************************************************
306  *          CoCreateFreeThreadedMarshaler [OLE32.@]
307  *
308  */
309 HRESULT WINAPI CoCreateFreeThreadedMarshaler (LPUNKNOWN punkOuter, LPUNKNOWN * ppunkMarshal)
310 {
311
312     FTMarshalImpl *ftm;
313
314     TRACE ("(%p %p)\n", punkOuter, ppunkMarshal);
315
316     ftm = HeapAlloc (GetProcessHeap (), 0, sizeof (FTMarshalImpl));
317     if (!ftm)
318         return E_OUTOFMEMORY;
319
320     ftm->lpVtbl = &iunkvt;
321     ftm->lpvtblFTM = &ftmvtbl;
322     ftm->ref = 1;
323     ftm->pUnkOuter = punkOuter ? punkOuter : _IFTMUnknown_(ftm);
324
325     *ppunkMarshal = _IFTMUnknown_ (ftm);
326     return S_OK;
327 }
328
329 static HRESULT WINAPI FTMarshalCF_QueryInterface(LPCLASSFACTORY iface,
330                                                   REFIID riid, LPVOID *ppv)
331 {
332     *ppv = NULL;
333     if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory))
334     {
335         *ppv = iface;
336         IUnknown_AddRef(iface);
337         return S_OK;
338     }
339     return E_NOINTERFACE;
340 }
341
342 static ULONG WINAPI FTMarshalCF_AddRef(LPCLASSFACTORY iface)
343 {
344     return 2; /* non-heap based object */
345 }
346
347 static ULONG WINAPI FTMarshalCF_Release(LPCLASSFACTORY iface)
348 {
349     return 1; /* non-heap based object */
350 }
351
352 static HRESULT WINAPI FTMarshalCF_CreateInstance(LPCLASSFACTORY iface,
353     LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv)
354 {
355     IUnknown *pUnknown;
356     HRESULT  hr;
357
358     TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv);
359
360     *ppv = NULL;
361
362     hr = CoCreateFreeThreadedMarshaler(pUnk, &pUnknown);
363
364     if (SUCCEEDED(hr))
365     {
366         hr = IUnknown_QueryInterface(pUnknown, riid, ppv);
367         IUnknown_Release(pUnknown);
368     }
369
370     return hr;
371 }
372
373 static HRESULT WINAPI FTMarshalCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)
374 {
375     FIXME("(%d), stub!\n",fLock);
376     return S_OK;
377 }
378
379 static const IClassFactoryVtbl FTMarshalCFVtbl =
380 {
381     FTMarshalCF_QueryInterface,
382     FTMarshalCF_AddRef,
383     FTMarshalCF_Release,
384     FTMarshalCF_CreateInstance,
385     FTMarshalCF_LockServer
386 };
387 static const IClassFactoryVtbl *FTMarshalCF = &FTMarshalCFVtbl;
388
389 HRESULT FTMarshalCF_Create(REFIID riid, LPVOID *ppv)
390 {
391     return IClassFactory_QueryInterface((IClassFactory *)&FTMarshalCF, riid, ppv);
392 }