iphlpapi: Clean up memory allocation.
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 WINE_DEFAULT_DEBUG_CHANNEL(ole);
38
39 typedef struct _FTMarshalImpl {
40         const IUnknownVtbl *lpVtbl;
41         LONG ref;
42         const IMarshalVtbl *lpvtblFTM;
43
44         IUnknown *pUnkOuter;
45 } FTMarshalImpl;
46
47 #define _IFTMUnknown_(This)(IUnknown*)&(This->lpVtbl)
48 #define _IFTMarshal_(This) (IMarshal*)&(This->lpvtblFTM)
49
50 static inline FTMarshalImpl *impl_from_IMarshal( IMarshal *iface )
51 {
52     return (FTMarshalImpl *)((char*)iface - FIELD_OFFSET(FTMarshalImpl, lpvtblFTM));
53 }
54
55 /* inner IUnknown to handle aggregation */
56 static HRESULT WINAPI
57 IiFTMUnknown_fnQueryInterface (IUnknown * iface, REFIID riid, LPVOID * ppv)
58 {
59
60     FTMarshalImpl *This = (FTMarshalImpl *)iface;
61
62     TRACE ("\n");
63     *ppv = NULL;
64
65     if (IsEqualIID (&IID_IUnknown, riid))
66         *ppv = _IFTMUnknown_ (This);
67     else if (IsEqualIID (&IID_IMarshal, riid))
68         *ppv = _IFTMarshal_ (This);
69     else {
70         FIXME ("No interface for %s.\n", debugstr_guid (riid));
71         return E_NOINTERFACE;
72     }
73     IUnknown_AddRef ((IUnknown *) * ppv);
74     return S_OK;
75 }
76
77 static ULONG WINAPI IiFTMUnknown_fnAddRef (IUnknown * iface)
78 {
79
80     FTMarshalImpl *This = (FTMarshalImpl *)iface;
81
82     TRACE ("\n");
83     return InterlockedIncrement (&This->ref);
84 }
85
86 static ULONG WINAPI IiFTMUnknown_fnRelease (IUnknown * iface)
87 {
88
89     FTMarshalImpl *This = (FTMarshalImpl *)iface;
90
91     TRACE ("\n");
92     if (InterlockedDecrement (&This->ref))
93         return This->ref;
94     HeapFree (GetProcessHeap (), 0, This);
95     return 0;
96 }
97
98 static const IUnknownVtbl iunkvt =
99 {
100         IiFTMUnknown_fnQueryInterface,
101         IiFTMUnknown_fnAddRef,
102         IiFTMUnknown_fnRelease
103 };
104
105 static HRESULT WINAPI
106 FTMarshalImpl_QueryInterface (LPMARSHAL iface, REFIID riid, LPVOID * ppv)
107 {
108
109     FTMarshalImpl *This = impl_from_IMarshal(iface);
110
111     TRACE ("(%p)->(\n\tIID:\t%s,%p)\n", This, debugstr_guid (riid), ppv);
112     return IUnknown_QueryInterface (This->pUnkOuter, riid, ppv);
113 }
114
115 static ULONG WINAPI
116 FTMarshalImpl_AddRef (LPMARSHAL iface)
117 {
118
119     FTMarshalImpl *This = impl_from_IMarshal(iface);
120
121     TRACE ("\n");
122     return IUnknown_AddRef (This->pUnkOuter);
123 }
124
125 static ULONG WINAPI
126 FTMarshalImpl_Release (LPMARSHAL iface)
127 {
128
129     FTMarshalImpl *This = impl_from_IMarshal(iface);
130
131     TRACE ("\n");
132     return IUnknown_Release (This->pUnkOuter);
133 }
134
135 static HRESULT WINAPI
136 FTMarshalImpl_GetUnmarshalClass (LPMARSHAL iface, REFIID riid, void *pv, DWORD dwDestContext,
137                                                 void *pvDestContext, DWORD mshlflags, CLSID * pCid)
138 {
139     FIXME ("(), stub!\n");
140     return S_OK;
141 }
142
143 static HRESULT WINAPI
144 FTMarshalImpl_GetMarshalSizeMax (LPMARSHAL iface, REFIID riid, void *pv, DWORD dwDestContext,
145                                                 void *pvDestContext, DWORD mshlflags, DWORD * pSize)
146 {
147
148     IMarshal *pMarshal = NULL;
149     HRESULT hres;
150
151     FTMarshalImpl *This = impl_from_IMarshal(iface);
152
153     FIXME ("(), stub!\n");
154
155     /* if the marshalling happens inside the same process the interface pointer is
156        copied between the apartments */
157     if (dwDestContext == MSHCTX_INPROC || dwDestContext == MSHCTX_CROSSCTX) {
158         *pSize = sizeof (This);
159         return S_OK;
160     }
161
162     /* use the standard marshaller to handle all other cases */
163     CoGetStandardMarshal (riid, pv, dwDestContext, pvDestContext, mshlflags, &pMarshal);
164     hres = IMarshal_GetMarshalSizeMax (pMarshal, riid, pv, dwDestContext, pvDestContext, mshlflags, pSize);
165     IMarshal_Release (pMarshal);
166     return hres;
167 }
168
169 static HRESULT WINAPI
170 FTMarshalImpl_MarshalInterface (LPMARSHAL iface, IStream * pStm, REFIID riid, void *pv,
171                                DWORD dwDestContext, void *pvDestContext, DWORD mshlflags)
172 {
173
174     IMarshal *pMarshal = NULL;
175     HRESULT hres;
176
177     FTMarshalImpl *This = impl_from_IMarshal(iface);
178
179     FIXME ("(), stub!\n");
180
181     /* if the marshalling happens inside the same process the interface pointer is
182        copied between the apartments */
183     if (dwDestContext == MSHCTX_INPROC || dwDestContext == MSHCTX_CROSSCTX) {
184         return IStream_Write (pStm, This, sizeof (This), 0);
185     }
186
187     /* use the standard marshaler to handle all other cases */
188     CoGetStandardMarshal (riid, pv, dwDestContext, pvDestContext, mshlflags, &pMarshal);
189     hres = IMarshal_MarshalInterface (pMarshal, pStm, riid, pv, dwDestContext, pvDestContext, mshlflags);
190     IMarshal_Release (pMarshal);
191     return hres;
192 }
193
194 static HRESULT WINAPI
195 FTMarshalImpl_UnmarshalInterface (LPMARSHAL iface, IStream * pStm, REFIID riid, void **ppv)
196 {
197     FIXME ("(), stub!\n");
198     return S_OK;
199 }
200
201 static HRESULT WINAPI FTMarshalImpl_ReleaseMarshalData (LPMARSHAL iface, IStream * pStm)
202 {
203     FIXME ("(), stub!\n");
204     return S_OK;
205 }
206
207 static HRESULT WINAPI FTMarshalImpl_DisconnectObject (LPMARSHAL iface, DWORD dwReserved)
208 {
209     FIXME ("(), stub!\n");
210     return S_OK;
211 }
212
213 static const IMarshalVtbl ftmvtbl =
214 {
215         FTMarshalImpl_QueryInterface,
216         FTMarshalImpl_AddRef,
217         FTMarshalImpl_Release,
218         FTMarshalImpl_GetUnmarshalClass,
219         FTMarshalImpl_GetMarshalSizeMax,
220         FTMarshalImpl_MarshalInterface,
221         FTMarshalImpl_UnmarshalInterface,
222         FTMarshalImpl_ReleaseMarshalData,
223         FTMarshalImpl_DisconnectObject
224 };
225
226 /***********************************************************************
227  *          CoCreateFreeThreadedMarshaler [OLE32.@]
228  *
229  */
230 HRESULT WINAPI CoCreateFreeThreadedMarshaler (LPUNKNOWN punkOuter, LPUNKNOWN * ppunkMarshal)
231 {
232
233     FTMarshalImpl *ftm;
234
235     TRACE ("(%p %p)\n", punkOuter, ppunkMarshal);
236
237     ftm = HeapAlloc (GetProcessHeap (), 0, sizeof (FTMarshalImpl));
238     if (!ftm)
239         return E_OUTOFMEMORY;
240
241     ftm->lpVtbl = &iunkvt;
242     ftm->lpvtblFTM = &ftmvtbl;
243     ftm->ref = 1;
244     ftm->pUnkOuter = punkOuter;
245
246     *ppunkMarshal = _IFTMUnknown_ (ftm);
247     return S_OK;
248 }