msdaps: Implement the marshalling object.
[wine] / dlls / msdaps / row_server.c
1 /*
2  *    Row and rowset servers / proxies.
3  *
4  * Copyright 2010 Huw Davies
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 #include <stdarg.h>
21 #include <string.h>
22
23 #define COBJMACROS
24 #define NONAMELESSUNION
25 #define NONAMELESSSTRUCT
26
27 #include "windef.h"
28 #include "winbase.h"
29 #include "wingdi.h"
30 #include "winuser.h"
31 #include "winerror.h"
32 #include "objbase.h"
33 #include "oleauto.h"
34 #include "oledb.h"
35
36 #include "row_server.h"
37
38 #include "wine/debug.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(oledb);
41
42
43 typedef struct
44 {
45     const IWineRowServerVtbl *vtbl;
46
47     LONG ref;
48
49     CLSID class;
50     IMarshal *marshal;
51     IUnknown *inner_unk;
52 } server;
53
54 static inline server *impl_from_IWineRowServer(IWineRowServer *iface)
55 {
56     return (server *)((char*)iface - FIELD_OFFSET(server, vtbl));
57 }
58
59 static HRESULT WINAPI server_QueryInterface(IWineRowServer *iface, REFIID riid, void **obj)
60 {
61     server *This = impl_from_IWineRowServer(iface);
62     TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), obj);
63
64     *obj = NULL;
65
66     if(IsEqualIID(riid, &IID_IUnknown) ||
67        IsEqualIID(riid, &IID_IWineRowServer))
68     {
69         *obj = iface;
70     }
71     else
72     {
73         if(!IsEqualIID(riid, &IID_IMarshal)) /* We use standard marshalling */
74             FIXME("interface %s not implemented\n", debugstr_guid(riid));
75         return E_NOINTERFACE;
76     }
77
78     IWineRowServer_AddRef(iface);
79     return S_OK;
80 }
81
82 static ULONG WINAPI server_AddRef(IWineRowServer *iface)
83 {
84     server *This = impl_from_IWineRowServer(iface);
85     TRACE("(%p)\n", This);
86
87     return InterlockedIncrement(&This->ref);
88 }
89
90 static ULONG WINAPI server_Release(IWineRowServer *iface)
91 {
92     server *This = impl_from_IWineRowServer(iface);
93     LONG ref;
94
95     TRACE("(%p)\n", This);
96
97     ref = InterlockedDecrement(&This->ref);
98     if(ref == 0)
99     {
100         IMarshal_Release(This->marshal);
101         if(This->inner_unk) IUnknown_Release(This->inner_unk);
102         HeapFree(GetProcessHeap(), 0, This);
103     }
104
105     return ref;
106 }
107
108 static HRESULT WINAPI server_SetInnerUnk(IWineRowServer *iface, IUnknown *inner)
109 {
110     server *This = impl_from_IWineRowServer(iface);
111
112     if(This->inner_unk) IUnknown_Release(This->inner_unk);
113
114     if(inner) IUnknown_AddRef(inner);
115     This->inner_unk = inner;
116     return S_OK;
117 }
118
119 static HRESULT WINAPI server_GetMarshal(IWineRowServer *iface, IMarshal **marshal)
120 {
121     server *This = impl_from_IWineRowServer(iface);
122
123     IMarshal_AddRef(This->marshal);
124     *marshal = This->marshal;
125     return S_OK;
126 }
127
128 static const IWineRowServerVtbl server_vtbl =
129 {
130     server_QueryInterface,
131     server_AddRef,
132     server_Release,
133     server_SetInnerUnk,
134     server_GetMarshal
135 };
136
137 static HRESULT create_server(IUnknown *outer, const CLSID *class, void **obj)
138 {
139     server *server;
140     TRACE("(%p, %s, %p)\n", outer, debugstr_guid(class), obj);
141
142     *obj = NULL;
143
144     server = HeapAlloc(GetProcessHeap(), 0, sizeof(*server));
145     if(!server) return E_OUTOFMEMORY;
146
147     server->vtbl = &server_vtbl;
148     server->ref = 1;
149     server->class = *class;
150     server->inner_unk = NULL;
151     if(IsEqualGUID(class, &CLSID_wine_row_server))
152         create_row_marshal((IUnknown*)server, (void**)&server->marshal);
153     else if(IsEqualGUID(class, &CLSID_wine_rowset_server))
154         create_rowset_marshal((IUnknown*)server, (void**)&server->marshal);
155     else
156         ERR("create_server called with class %s\n", debugstr_guid(class));
157
158     *obj = server;
159     return S_OK;
160 }
161
162 HRESULT create_row_server(IUnknown *outer, void **obj)
163 {
164     return create_server(outer, &CLSID_wine_row_server, obj);
165 }
166
167 HRESULT create_rowset_server(IUnknown *outer, void **obj)
168 {
169     return create_server(outer, &CLSID_wine_rowset_server, obj);
170 }
171
172 HRESULT create_proxy(IWineRowServer *server, const CLSID *class, IUnknown **obj)
173 {
174     FIXME("stub\n");
175     *obj = NULL;
176     return E_NOTIMPL;
177 }
178
179 /* Marshal impl */
180
181 typedef struct
182 {
183     const IMarshalVtbl *marshal_vtbl;
184
185     LONG ref;
186     CLSID unmarshal_class;
187     IUnknown *outer;
188 } marshal;
189
190 static inline marshal *impl_from_IMarshal(IMarshal *iface)
191 {
192     return (marshal *)((char*)iface - FIELD_OFFSET(marshal, marshal_vtbl));
193 }
194
195 static HRESULT WINAPI marshal_QueryInterface(IMarshal *iface, REFIID iid, void **obj)
196 {
197     marshal *This = impl_from_IMarshal(iface);
198     TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(iid), obj);
199
200     if(IsEqualIID(iid, &IID_IUnknown) ||
201        IsEqualIID(iid, &IID_IMarshal))
202     {
203         *obj = iface;
204     }
205     else
206     {
207         FIXME("interface %s not implemented\n", debugstr_guid(iid));
208         *obj = NULL;
209         return E_NOINTERFACE;
210     }
211
212     IMarshal_AddRef(iface);
213     return S_OK;
214 }
215
216 static ULONG WINAPI marshal_AddRef(IMarshal *iface)
217 {
218     marshal *This = impl_from_IMarshal(iface);
219     TRACE("(%p)\n", This);
220     return InterlockedIncrement(&This->ref);
221 }
222
223 static ULONG WINAPI marshal_Release(IMarshal *iface)
224 {
225     marshal *This = impl_from_IMarshal(iface);
226     LONG ref;
227
228     TRACE("(%p)\n", This);
229
230     ref = InterlockedDecrement(&This->ref);
231     if(ref == 0)
232     {
233         HeapFree(GetProcessHeap(), 0, This);
234     }
235
236     return ref;
237 }
238
239 static HRESULT WINAPI marshal_GetUnmarshalClass(IMarshal *iface, REFIID iid, void *obj,
240                                                 DWORD dwDestContext, void *pvDestContext,
241                                                 DWORD mshlflags, CLSID *clsid)
242 {
243     marshal *This = impl_from_IMarshal(iface);
244     TRACE("(%p)->(%s, %p, %08x, %p, %08x, %p)\n", This, debugstr_guid(iid), obj, dwDestContext,
245           pvDestContext, mshlflags, clsid);
246
247     *clsid = This->unmarshal_class;
248     return S_OK;
249 }
250
251 static HRESULT WINAPI marshal_GetMarshalSizeMax(IMarshal *iface, REFIID iid, void *obj,
252                                                 DWORD dwDestContext, void *pvDestContext,
253                                                 DWORD mshlflags, DWORD *size)
254 {
255     marshal *This = impl_from_IMarshal(iface);
256     TRACE("(%p)->(%s, %p, %08x, %p, %08x, %p)\n", This, debugstr_guid(iid), obj, dwDestContext,
257           pvDestContext, mshlflags, size);
258
259     return CoGetMarshalSizeMax(size, &IID_IWineRowServer, This->outer, dwDestContext, pvDestContext,
260                                mshlflags);
261 }
262
263 static HRESULT WINAPI marshal_MarshalInterface(IMarshal *iface, IStream *stream, REFIID iid,
264                                                void *obj, DWORD dwDestContext, void *pvDestContext,
265                                                DWORD mshlflags)
266 {
267     marshal *This = impl_from_IMarshal(iface);
268     TRACE("(%p)->(%p, %s, %p, %08x, %p, %08x)\n", This, stream, debugstr_guid(iid), obj, dwDestContext,
269           pvDestContext, mshlflags);
270
271     return CoMarshalInterface(stream, &IID_IWineRowServer, This->outer, dwDestContext, pvDestContext, mshlflags);
272 }
273
274 static HRESULT WINAPI marshal_UnmarshalInterface(IMarshal *iface, IStream *stream,
275                                                  REFIID iid, void **obj)
276 {
277     marshal *This = impl_from_IMarshal(iface);
278     HRESULT hr;
279     IWineRowServer *server;
280     IUnknown *proxy;
281
282     TRACE("(%p)->(%p, %s, %p)\n", This, stream, debugstr_guid(iid), obj);
283     *obj = NULL;
284
285     hr = CoUnmarshalInterface(stream, &IID_IWineRowServer, (void**)&server);
286     if(SUCCEEDED(hr))
287     {
288         hr = create_proxy(server, &This->unmarshal_class, &proxy);
289         if(SUCCEEDED(hr))
290         {
291             hr = IUnknown_QueryInterface(proxy, iid, obj);
292             IUnknown_Release(proxy);
293         }
294         IWineRowServer_Release(server);
295     }
296
297     TRACE("returing %p\n", *obj);
298     return hr;
299 }
300
301 static HRESULT WINAPI marshal_ReleaseMarshalData(IMarshal *iface, IStream *stream)
302 {
303     marshal *This = impl_from_IMarshal(iface);
304     TRACE("(%p)->(%p)\n", This, stream);
305     return CoReleaseMarshalData(stream);
306 }
307
308 static HRESULT WINAPI marshal_DisconnectObject(IMarshal *iface, DWORD dwReserved)
309 {
310     marshal *This = impl_from_IMarshal(iface);
311     FIXME("(%p)->(%08x)\n", This, dwReserved);
312
313     return E_NOTIMPL;
314 }
315
316 static const IMarshalVtbl marshal_vtbl =
317 {
318     marshal_QueryInterface,
319     marshal_AddRef,
320     marshal_Release,
321     marshal_GetUnmarshalClass,
322     marshal_GetMarshalSizeMax,
323     marshal_MarshalInterface,
324     marshal_UnmarshalInterface,
325     marshal_ReleaseMarshalData,
326     marshal_DisconnectObject
327 };
328
329 static HRESULT create_marshal(IUnknown *outer, const CLSID *class, void **obj)
330 {
331     marshal *marshal;
332
333     TRACE("(%p, %p)\n", outer, obj);
334     *obj = NULL;
335
336     marshal = HeapAlloc(GetProcessHeap(), 0, sizeof(*marshal));
337     if(!marshal) return E_OUTOFMEMORY;
338
339     marshal->unmarshal_class = *class;
340     marshal->outer = outer; /* don't ref outer unk */
341     marshal->marshal_vtbl = &marshal_vtbl;
342     marshal->ref = 1;
343
344     *obj = &marshal->marshal_vtbl;
345     TRACE("returing %p\n", *obj);
346     return S_OK;
347 }
348
349 HRESULT create_row_marshal(IUnknown *outer, void **obj)
350 {
351     TRACE("(%p, %p)\n", outer, obj);
352     return create_marshal(outer, &CLSID_wine_row_proxy, obj);
353 }
354
355 HRESULT create_rowset_marshal(IUnknown *outer, void **obj)
356 {
357     TRACE("(%p, %p)\n", outer, obj);
358     return create_marshal(outer, &CLSID_wine_rowset_proxy, obj);
359 }