ntdll/tests: Add test for RtlIpv4StringToAddress.
[wine/multimedia.git] / dlls / msdaps / row_server.c
blobab4ae9c693c67a0dca74392abb01ddb6f9a5b07e
1 /*
2 * Row and rowset servers / proxies.
4 * Copyright 2010 Huw Davies
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
20 #include <stdarg.h>
21 #include <string.h>
23 #define COBJMACROS
24 #define NONAMELESSUNION
25 #define NONAMELESSSTRUCT
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"
36 #include "row_server.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(oledb);
42 static inline DBLENGTH db_type_size(DBTYPE type, DBLENGTH var_len)
44 switch(type)
46 case DBTYPE_I1:
47 case DBTYPE_UI1:
48 return 1;
49 case DBTYPE_I2:
50 case DBTYPE_UI2:
51 return 2;
52 case DBTYPE_I4:
53 case DBTYPE_UI4:
54 case DBTYPE_R4:
55 return 4;
56 case DBTYPE_I8:
57 case DBTYPE_UI8:
58 case DBTYPE_R8:
59 return 8;
60 case DBTYPE_CY:
61 return sizeof(CY);
62 case DBTYPE_FILETIME:
63 return sizeof(FILETIME);
64 case DBTYPE_BSTR:
65 return sizeof(BSTR);
66 case DBTYPE_GUID:
67 return sizeof(GUID);
68 case DBTYPE_WSTR:
69 return var_len;
70 default:
71 FIXME("Unhandled type %04x\n", type);
72 return 0;
76 typedef struct
78 IWineRowServer IWineRowServer_iface;
80 LONG ref;
82 CLSID class;
83 IMarshal *marshal;
84 IUnknown *inner_unk;
85 } server;
87 static inline server *impl_from_IWineRowServer(IWineRowServer *iface)
89 return CONTAINING_RECORD(iface, server, IWineRowServer_iface);
92 static HRESULT WINAPI server_QueryInterface(IWineRowServer *iface, REFIID riid, void **obj)
94 server *This = impl_from_IWineRowServer(iface);
95 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), obj);
97 *obj = NULL;
99 if(IsEqualIID(riid, &IID_IUnknown) ||
100 IsEqualIID(riid, &IID_IWineRowServer))
102 *obj = iface;
104 else
106 if(!IsEqualIID(riid, &IID_IMarshal)) /* We use standard marshalling */
107 FIXME("interface %s not implemented\n", debugstr_guid(riid));
108 return E_NOINTERFACE;
111 IWineRowServer_AddRef(iface);
112 return S_OK;
115 static ULONG WINAPI server_AddRef(IWineRowServer *iface)
117 server *This = impl_from_IWineRowServer(iface);
118 TRACE("(%p)\n", This);
120 return InterlockedIncrement(&This->ref);
123 static ULONG WINAPI server_Release(IWineRowServer *iface)
125 server *This = impl_from_IWineRowServer(iface);
126 LONG ref;
128 TRACE("(%p)\n", This);
130 ref = InterlockedDecrement(&This->ref);
131 if(ref == 0)
133 IMarshal_Release(This->marshal);
134 if(This->inner_unk) IUnknown_Release(This->inner_unk);
135 HeapFree(GetProcessHeap(), 0, This);
138 return ref;
141 static HRESULT WINAPI server_SetInnerUnk(IWineRowServer *iface, IUnknown *inner)
143 server *This = impl_from_IWineRowServer(iface);
145 if(This->inner_unk) IUnknown_Release(This->inner_unk);
147 if(inner) IUnknown_AddRef(inner);
148 This->inner_unk = inner;
149 return S_OK;
152 static HRESULT WINAPI server_GetMarshal(IWineRowServer *iface, IMarshal **marshal)
154 server *This = impl_from_IWineRowServer(iface);
156 IMarshal_AddRef(This->marshal);
157 *marshal = This->marshal;
158 return S_OK;
161 static HRESULT WINAPI server_GetColumns(IWineRowServer* iface, DBORDINAL num_cols,
162 wine_getcolumns_in *in_data, wine_getcolumns_out *out_data)
164 server *This = impl_from_IWineRowServer(iface);
165 HRESULT hr;
166 DBORDINAL i;
167 DBCOLUMNACCESS *cols;
168 IRow *row;
170 TRACE("(%p)->(%ld, %p, %p)\n", This, num_cols, in_data, out_data);
172 hr = IUnknown_QueryInterface(This->inner_unk, &IID_IRow, (void**)&row);
173 if(FAILED(hr)) return hr;
175 cols = CoTaskMemAlloc(num_cols * sizeof(cols[0]));
177 for(i = 0; i < num_cols; i++)
179 TRACE("%ld:\tmax_len %ld type %04x\n", i, in_data[i].max_len, in_data[i].type);
180 cols[i].pData = CoTaskMemAlloc(db_type_size(in_data[i].type, in_data[i].max_len));
181 cols[i].columnid = in_data[i].columnid;
182 cols[i].cbMaxLen = in_data[i].max_len;
183 cols[i].wType = in_data[i].type;
184 cols[i].bPrecision = in_data[i].precision;
185 cols[i].bScale = in_data[i].scale;
188 hr = IRow_GetColumns(row, num_cols, cols);
189 IRow_Release(row);
191 for(i = 0; i < num_cols; i++)
193 VariantInit(&out_data[i].v);
194 if(cols[i].dwStatus == DBSTATUS_S_OK)
196 V_VT(&out_data[i].v) = in_data[i].type;
197 memcpy(&V_I1(&out_data[i].v), cols[i].pData, cols[i].cbDataLen);
199 CoTaskMemFree(cols[i].pData);
200 out_data[i].data_len = cols[i].cbDataLen;
201 out_data[i].status = cols[i].dwStatus;
204 CoTaskMemFree(cols);
206 return hr;
209 static HRESULT WINAPI server_GetSourceRowset(IWineRowServer* iface, REFIID riid, IUnknown **ppRowset,
210 HROW *phRow)
212 server *This = impl_from_IWineRowServer(iface);
213 FIXME("(%p): stub\n", This);
214 return E_NOTIMPL;
217 static HRESULT WINAPI server_Open(IWineRowServer* iface, IUnknown *pUnkOuter, DBID *pColumnID,
218 REFGUID rguidColumnType, DWORD dwBindFlags, REFIID riid,
219 IUnknown **ppUnk)
221 server *This = impl_from_IWineRowServer(iface);
222 IRow *row;
223 HRESULT hr;
224 IWineRowServer *new_server;
225 IMarshal *marshal;
226 IUnknown *obj;
228 TRACE("(%p)->(%p, %p, %s, %08x, %s, %p)\n", This, pUnkOuter, pColumnID, debugstr_guid(rguidColumnType),
229 dwBindFlags, debugstr_guid(riid), ppUnk);
231 *ppUnk = NULL;
233 hr = IUnknown_QueryInterface(This->inner_unk, &IID_IRow, (void**)&row);
234 if(FAILED(hr)) return hr;
236 if(IsEqualGUID(rguidColumnType, &DBGUID_ROWSET))
237 hr = CoCreateInstance(&CLSID_wine_rowset_server, NULL, CLSCTX_INPROC_SERVER, &IID_IWineRowServer, (void**)&new_server);
238 else
240 FIXME("Unhandled object %s\n", debugstr_guid(rguidColumnType));
241 hr = E_NOTIMPL;
244 if(FAILED(hr))
246 IRow_Release(row);
247 return hr;
250 IWineRowServer_GetMarshal(new_server, &marshal);
251 hr = IRow_Open(row, (IUnknown*)marshal, pColumnID, rguidColumnType, dwBindFlags, &IID_IUnknown, &obj);
252 IMarshal_Release(marshal);
253 IRow_Release(row);
255 if(FAILED(hr))
257 IWineRowServer_Release(new_server);
258 return hr;
261 IWineRowServer_SetInnerUnk(new_server, obj);
262 hr = IUnknown_QueryInterface(obj, riid, (void**)ppUnk);
263 IUnknown_Release(obj);
265 TRACE("returning %08x\n", hr);
266 return hr;
269 static HRESULT WINAPI server_SetColumns(IWineRowServer* iface, DBORDINAL num_cols,
270 wine_setcolumns_in *in_data, DBSTATUS *status)
272 server *This = impl_from_IWineRowServer(iface);
273 HRESULT hr;
274 DBORDINAL i;
275 DBCOLUMNACCESS *cols;
276 IRowChange *row_change;
278 TRACE("(%p)->(%ld, %p, %p)\n", This, num_cols, in_data, status);
279 hr = IUnknown_QueryInterface(This->inner_unk, &IID_IRowChange, (void**)&row_change);
280 if(FAILED(hr)) return hr;
282 cols = CoTaskMemAlloc(num_cols * sizeof(cols[0]));
284 for(i = 0; i < num_cols; i++)
286 TRACE("%ld:\ttype %04x\n", i, in_data[i].type);
287 cols[i].pData = CoTaskMemAlloc(db_type_size(in_data[i].type, in_data[i].max_len));
288 memcpy(cols[i].pData, &V_I1(&in_data[i].v), db_type_size(in_data[i].type, in_data[i].max_len));
289 cols[i].columnid = in_data[i].columnid;
290 cols[i].cbDataLen = in_data[i].data_len;
291 cols[i].dwStatus = in_data[i].status;
292 cols[i].cbMaxLen = in_data[i].max_len;
293 cols[i].wType = in_data[i].type;
294 cols[i].bPrecision = in_data[i].precision;
295 cols[i].bScale = in_data[i].scale;
298 hr = IRowChange_SetColumns(row_change, num_cols, cols);
299 IRowChange_Release(row_change);
301 for(i = 0; i < num_cols; i++)
303 CoTaskMemFree(cols[i].pData);
304 status[i] = cols[i].dwStatus;
307 CoTaskMemFree(cols);
309 return hr;
312 static HRESULT WINAPI server_AddRefRows(IWineRowServer* iface, DBCOUNTITEM cRows,
313 const HROW rghRows[], DBREFCOUNT rgRefCounts[],
314 DBROWSTATUS rgRowStatus[])
316 server *This = impl_from_IWineRowServer(iface);
317 IRowset *rowset;
318 HRESULT hr;
320 TRACE("(%p)->(%ld, %p, %p, %p)\n", This, cRows, rghRows, rgRefCounts, rgRowStatus);
322 hr = IUnknown_QueryInterface(This->inner_unk, &IID_IRowset, (void**)&rowset);
323 if(FAILED(hr)) return hr;
325 hr = IRowset_AddRefRows(rowset, cRows, rghRows, rgRefCounts, rgRowStatus);
327 IRowset_Release(rowset);
328 TRACE("returning %08x\n", hr);
329 return hr;
332 static HRESULT WINAPI server_GetData(IWineRowServer* iface, HROW hRow,
333 HACCESSOR hAccessor, BYTE *pData, DWORD size)
335 server *This = impl_from_IWineRowServer(iface);
336 IRowset *rowset;
337 HRESULT hr;
339 TRACE("(%p)->(%08lx, %08lx, %p, %d)\n", This, hRow, hAccessor, pData, size);
341 hr = IUnknown_QueryInterface(This->inner_unk, &IID_IRowset, (void**)&rowset);
342 if(FAILED(hr)) return hr;
344 hr = IRowset_GetData(rowset, hRow, hAccessor, pData);
346 IRowset_Release(rowset);
347 TRACE("returning %08x\n", hr);
348 return hr;
351 static HRESULT WINAPI server_GetNextRows(IWineRowServer* iface, HCHAPTER hReserved, DBROWOFFSET lRowsOffset,
352 DBROWCOUNT cRows, DBCOUNTITEM *pcRowObtained, HROW **prghRows)
354 server *This = impl_from_IWineRowServer(iface);
355 IRowset *rowset;
356 HRESULT hr;
358 TRACE("(%p)->(%08lx, %ld, %ld, %p, %p)\n", This, hReserved, lRowsOffset, cRows, pcRowObtained, prghRows);
360 hr = IUnknown_QueryInterface(This->inner_unk, &IID_IRowset, (void**)&rowset);
361 if(FAILED(hr)) return hr;
363 *prghRows = NULL;
365 hr = IRowset_GetNextRows(rowset, hReserved, lRowsOffset, cRows, pcRowObtained, prghRows);
366 IRowset_Release(rowset);
367 TRACE("returning %08x, got %ld rows\n", hr, *pcRowObtained);
368 return hr;
371 static HRESULT WINAPI server_ReleaseRows(IWineRowServer* iface, DBCOUNTITEM cRows, const HROW rghRows[],
372 DBROWOPTIONS rgRowOptions[], DBREFCOUNT rgRefCounts[], DBROWSTATUS rgRowStatus[])
374 server *This = impl_from_IWineRowServer(iface);
375 IRowset *rowset;
376 HRESULT hr;
378 TRACE("(%p)->(%ld, %p, %p, %p, %p)\n", This, cRows, rghRows, rgRowOptions, rgRefCounts, rgRowStatus);
380 hr = IUnknown_QueryInterface(This->inner_unk, &IID_IRowset, (void**)&rowset);
381 if(FAILED(hr)) return hr;
383 hr = IRowset_ReleaseRows(rowset, cRows, rghRows, rgRowOptions, rgRefCounts, rgRowStatus);
384 IRowset_Release(rowset);
386 TRACE("returning %08x\n", hr);
387 return hr;
390 static HRESULT WINAPI server_RestartPosition(IWineRowServer* iface, HCHAPTER hReserved)
392 server *This = impl_from_IWineRowServer(iface);
393 FIXME("(%p)->(%08lx): stub\n", This, hReserved);
394 return E_NOTIMPL;
397 static HRESULT WINAPI server_Compare(IWineRowServer *iface, HCHAPTER hReserved, DBBKMARK cbBookmark1,
398 const BYTE *pBookmark1, DBBKMARK cbBookmark2, const BYTE *pBookmark2,
399 DBCOMPARE *pComparison)
401 server *This = impl_from_IWineRowServer(iface);
402 FIXME("(%p): stub\n", This);
403 return E_NOTIMPL;
406 static HRESULT WINAPI server_GetRowsAt(IWineRowServer *iface, HWATCHREGION hReserved1, HCHAPTER hReserved2,
407 DBBKMARK cbBookmark, const BYTE *pBookmark, DBROWOFFSET lRowsOffset,
408 DBROWCOUNT cRows, DBCOUNTITEM *pcRowsObtained, HROW **prghRows)
410 server *This = impl_from_IWineRowServer(iface);
411 IRowsetLocate *rowsetlocate;
412 HRESULT hr;
414 TRACE("(%p)->(%08lx, %08lx, %ld, %p, %ld, %ld, %p, %p\n", This, hReserved1, hReserved2, cbBookmark, pBookmark, lRowsOffset, cRows,
415 pcRowsObtained, prghRows);
417 *prghRows = NULL;
419 hr = IUnknown_QueryInterface(This->inner_unk, &IID_IRowsetLocate, (void**)&rowsetlocate);
420 if(FAILED(hr)) return hr;
422 hr = IRowsetLocate_GetRowsAt(rowsetlocate, hReserved1, hReserved2, cbBookmark, pBookmark, lRowsOffset,
423 cRows, pcRowsObtained, prghRows);
424 IRowsetLocate_Release(rowsetlocate);
426 TRACE("returning %08x\n", hr);
427 return hr;
430 static HRESULT WINAPI server_GetRowsByBookmark(IWineRowServer *iface, HCHAPTER hReserved, DBCOUNTITEM cRows,
431 const DBBKMARK rgcbBookmarks[], const BYTE * rgpBookmarks[],
432 HROW rghRows[], DBROWSTATUS rgRowStatus[])
434 server *This = impl_from_IWineRowServer(iface);
435 FIXME("(%p): stub\n", This);
436 return E_NOTIMPL;
439 static HRESULT WINAPI server_Hash(IWineRowServer *iface, HCHAPTER hReserved, DBBKMARK cBookmarks,
440 const DBBKMARK rgcbBookmarks[], const BYTE * rgpBookmarks[],
441 DBHASHVALUE rgHashedValues[], DBROWSTATUS rgBookmarkStatus[])
443 server *This = impl_from_IWineRowServer(iface);
444 FIXME("(%p): stub\n", This);
445 return E_NOTIMPL;
448 static HRESULT WINAPI server_GetProperties(IWineRowServer* iface, ULONG cPropertyIDSets,
449 const DBPROPIDSET *rgPropertyIDSets, ULONG *pcPropertySets,
450 DBPROPSET **prgPropertySets)
452 server *This = impl_from_IWineRowServer(iface);
453 IRowsetInfo *rowsetinfo;
454 HRESULT hr;
456 TRACE("(%p)->(%d, %p, %p, %p)\n", This, cPropertyIDSets, rgPropertyIDSets, pcPropertySets, prgPropertySets);
458 hr = IUnknown_QueryInterface(This->inner_unk, &IID_IRowsetInfo, (void**)&rowsetinfo);
459 if(FAILED(hr)) return hr;
461 hr = IRowsetInfo_GetProperties(rowsetinfo, cPropertyIDSets, rgPropertyIDSets, pcPropertySets, prgPropertySets);
462 IRowsetInfo_Release(rowsetinfo);
464 TRACE("returning %08x\n", hr);
465 return hr;
468 static HRESULT WINAPI server_GetReferencedRowset(IWineRowServer* iface, DBORDINAL iOrdinal,
469 REFIID riid, IUnknown **ppReferencedRowset)
471 server *This = impl_from_IWineRowServer(iface);
472 FIXME("(%p): stub\n", This);
473 return E_NOTIMPL;
476 static HRESULT WINAPI server_GetSpecification(IWineRowServer* iface, REFIID riid,
477 IUnknown **ppSpecification)
479 server *This = impl_from_IWineRowServer(iface);
480 FIXME("(%p): stub\n", This);
481 return E_NOTIMPL;
484 static HRESULT WINAPI server_AddRefAccessor(IWineRowServer* iface, HACCESSOR hAccessor,
485 DBREFCOUNT *pcRefCount)
487 server *This = impl_from_IWineRowServer(iface);
488 FIXME("(%p): stub\n", This);
489 return E_NOTIMPL;
492 static HRESULT WINAPI server_CreateAccessor(IWineRowServer* iface, DBACCESSORFLAGS dwAccessorFlags,
493 DBCOUNTITEM cBindings, const DBBINDING *rgBindings, DBLENGTH cbRowSize,
494 HACCESSOR *phAccessor, DBBINDSTATUS *rgStatus)
496 server *This = impl_from_IWineRowServer(iface);
497 HRESULT hr;
498 IAccessor *accessor;
500 TRACE("(%p)->(%08x, %ld, %p, %ld, %p, %p)\n", This, dwAccessorFlags, cBindings, rgBindings, cbRowSize, phAccessor, rgStatus);
502 hr = IUnknown_QueryInterface(This->inner_unk, &IID_IAccessor, (void**)&accessor);
503 if(FAILED(hr)) return hr;
505 hr = IAccessor_CreateAccessor(accessor, dwAccessorFlags, cBindings, rgBindings, cbRowSize, phAccessor, rgStatus);
506 IAccessor_Release(accessor);
508 TRACE("returning %08x, accessor %08lx\n", hr, *phAccessor);
509 return hr;
512 static HRESULT WINAPI server_GetBindings(IWineRowServer* iface, HACCESSOR hAccessor,
513 DBACCESSORFLAGS *pdwAccessorFlags, DBCOUNTITEM *pcBindings,
514 DBBINDING **prgBindings)
516 server *This = impl_from_IWineRowServer(iface);
517 HRESULT hr;
518 IAccessor *accessor;
520 TRACE("(%p)->(%08lx, %p, %p, %p)\n", This, hAccessor, pdwAccessorFlags, pcBindings, prgBindings);
522 hr = IUnknown_QueryInterface(This->inner_unk, &IID_IAccessor, (void**)&accessor);
523 if(FAILED(hr)) return hr;
525 hr = IAccessor_GetBindings(accessor, hAccessor, pdwAccessorFlags, pcBindings, prgBindings);
526 IAccessor_Release(accessor);
528 TRACE("returning %08x\n", hr);
529 return hr;
532 static HRESULT WINAPI server_ReleaseAccessor(IWineRowServer* iface, HACCESSOR hAccessor,
533 DBREFCOUNT *pcRefCount)
535 server *This = impl_from_IWineRowServer(iface);
536 HRESULT hr;
537 IAccessor *accessor;
539 TRACE("(%p)->(%08lx, %p)\n", This, hAccessor, pcRefCount);
541 hr = IUnknown_QueryInterface(This->inner_unk, &IID_IAccessor, (void**)&accessor);
542 if(FAILED(hr)) return hr;
544 hr = IAccessor_ReleaseAccessor(accessor, hAccessor, pcRefCount);
545 IAccessor_Release(accessor);
547 return hr;
550 static const IWineRowServerVtbl server_vtbl =
552 server_QueryInterface,
553 server_AddRef,
554 server_Release,
555 server_SetInnerUnk,
556 server_GetMarshal,
557 server_GetColumns,
558 server_GetSourceRowset,
559 server_Open,
560 server_SetColumns,
561 server_AddRefRows,
562 server_GetData,
563 server_GetNextRows,
564 server_ReleaseRows,
565 server_RestartPosition,
566 server_Compare,
567 server_GetRowsAt,
568 server_GetRowsByBookmark,
569 server_Hash,
570 server_GetProperties,
571 server_GetReferencedRowset,
572 server_GetSpecification,
573 server_AddRefAccessor,
574 server_CreateAccessor,
575 server_GetBindings,
576 server_ReleaseAccessor
579 static HRESULT create_server(IUnknown *outer, const CLSID *class, void **obj)
581 server *server;
582 TRACE("(%p, %s, %p)\n", outer, debugstr_guid(class), obj);
584 *obj = NULL;
586 server = HeapAlloc(GetProcessHeap(), 0, sizeof(*server));
587 if(!server) return E_OUTOFMEMORY;
589 server->IWineRowServer_iface.lpVtbl = &server_vtbl;
590 server->ref = 1;
591 server->class = *class;
592 server->inner_unk = NULL;
593 if(IsEqualGUID(class, &CLSID_wine_row_server))
594 create_row_marshal((IUnknown*)server, (void**)&server->marshal);
595 else if(IsEqualGUID(class, &CLSID_wine_rowset_server))
596 create_rowset_marshal((IUnknown*)server, (void**)&server->marshal);
597 else
598 ERR("create_server called with class %s\n", debugstr_guid(class));
600 *obj = server;
601 return S_OK;
604 HRESULT create_row_server(IUnknown *outer, void **obj)
606 return create_server(outer, &CLSID_wine_row_server, obj);
609 HRESULT create_rowset_server(IUnknown *outer, void **obj)
611 return create_server(outer, &CLSID_wine_rowset_server, obj);
614 typedef struct
616 IRow IRow_iface;
617 IRowChange IRowChange_iface;
619 LONG ref;
621 IWineRowServer *server;
622 } row_proxy;
624 static inline row_proxy *impl_from_IRow(IRow *iface)
626 return CONTAINING_RECORD(iface, row_proxy, IRow_iface);
629 static inline row_proxy *impl_from_IRowChange(IRowChange *iface)
631 return CONTAINING_RECORD(iface, row_proxy, IRowChange_iface);
634 static HRESULT WINAPI row_QueryInterface(IRow *iface, REFIID iid, void **obj)
636 row_proxy *This = impl_from_IRow(iface);
637 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(iid), obj);
639 if(IsEqualIID(iid, &IID_IUnknown) ||
640 IsEqualIID(iid, &IID_IRow))
642 *obj = &This->IRow_iface;
644 else if(IsEqualIID(iid, &IID_IRowChange))
646 *obj = &This->IRowChange_iface;
648 else
650 FIXME("interface %s not implemented\n", debugstr_guid(iid));
651 return E_NOINTERFACE;
654 IRow_AddRef(iface);
655 return S_OK;
658 static ULONG WINAPI row_AddRef(IRow *iface)
660 row_proxy *This = impl_from_IRow(iface);
661 TRACE("(%p)\n", This);
663 return InterlockedIncrement(&This->ref);
666 static ULONG WINAPI row_Release(IRow *iface)
668 row_proxy *This = impl_from_IRow(iface);
669 LONG ref;
671 TRACE("(%p)\n", This);
673 ref = InterlockedDecrement(&This->ref);
674 if(ref == 0)
676 if(This->server) IWineRowServer_Release(This->server);
677 HeapFree(GetProcessHeap(), 0, This);
680 return ref;
683 static HRESULT WINAPI row_GetColumns(IRow* iface, DBORDINAL cColumns, DBCOLUMNACCESS rgColumns[])
685 row_proxy *This = impl_from_IRow(iface);
686 DBORDINAL i;
687 wine_getcolumns_in *in_data;
688 wine_getcolumns_out *out_data;
689 HRESULT hr;
691 TRACE("(%p)->(%ld, %p)\n", This, cColumns, rgColumns);
693 in_data = CoTaskMemAlloc(cColumns * sizeof(in_data[0]));
694 out_data = CoTaskMemAlloc(cColumns * sizeof(out_data[0]));
696 for(i = 0; i < cColumns; i++)
698 TRACE("%ld:\tdata %p data_len %ld status %08x max_len %ld type %04x\n", i, rgColumns[i].pData,
699 rgColumns[i].cbDataLen, rgColumns[i].dwStatus, rgColumns[i].cbMaxLen, rgColumns[i].wType);
700 in_data[i].columnid = rgColumns[i].columnid;
701 in_data[i].max_len = rgColumns[i].cbMaxLen;
702 in_data[i].type = rgColumns[i].wType;
703 in_data[i].precision = rgColumns[i].bPrecision;
704 in_data[i].scale = rgColumns[i].bScale;
707 hr = IWineRowServer_GetColumns(This->server, cColumns, in_data, out_data);
709 for(i = 0; i < cColumns; i++)
711 rgColumns[i].cbDataLen = out_data[i].data_len;
712 rgColumns[i].dwStatus = out_data[i].status;
713 if(rgColumns[i].dwStatus == DBSTATUS_S_OK)
714 memcpy(rgColumns[i].pData, &V_I1(&out_data[i].v), out_data[i].data_len);
717 CoTaskMemFree(out_data);
718 CoTaskMemFree(in_data);
719 return hr;
722 static HRESULT WINAPI row_GetSourceRowset(IRow* iface, REFIID riid, IUnknown **ppRowset,
723 HROW *phRow)
725 row_proxy *This = impl_from_IRow(iface);
727 FIXME("(%p)->(%s, %p, %p): stub\n", This, debugstr_guid(riid), ppRowset, phRow);
729 return E_NOTIMPL;
732 static HRESULT WINAPI row_Open(IRow* iface, IUnknown *pUnkOuter,
733 DBID *pColumnID, REFGUID rguidColumnType,
734 DWORD dwBindFlags, REFIID riid, IUnknown **ppUnk)
736 row_proxy *This = impl_from_IRow(iface);
738 TRACE("(%p)->(%p, %p, %s, %08x, %s, %p)\n", This, pUnkOuter, pColumnID, debugstr_guid(rguidColumnType),
739 dwBindFlags, debugstr_guid(riid), ppUnk);
740 if(pUnkOuter)
742 FIXME("Aggregation not supported\n");
743 return CLASS_E_NOAGGREGATION;
746 return IWineRowServer_Open(This->server, pUnkOuter, pColumnID, rguidColumnType, dwBindFlags, riid, ppUnk);
749 static const IRowVtbl row_vtbl =
751 row_QueryInterface,
752 row_AddRef,
753 row_Release,
754 row_GetColumns,
755 row_GetSourceRowset,
756 row_Open
759 static HRESULT WINAPI row_change_QueryInterface(IRowChange *iface, REFIID iid, void **obj)
761 row_proxy *This = impl_from_IRowChange(iface);
762 return IUnknown_QueryInterface((IUnknown *)This, iid, obj);
765 static ULONG WINAPI row_change_AddRef(IRowChange *iface)
767 row_proxy *This = impl_from_IRowChange(iface);
768 return IUnknown_AddRef((IUnknown*)This);
771 static ULONG WINAPI row_change_Release(IRowChange *iface)
773 row_proxy *This = impl_from_IRowChange(iface);
774 return IUnknown_Release((IUnknown*)This);
777 static HRESULT WINAPI row_change_SetColumns(IRowChange *iface, DBORDINAL cColumns,
778 DBCOLUMNACCESS rgColumns[])
780 row_proxy *This = impl_from_IRowChange(iface);
781 HRESULT hr;
782 wine_setcolumns_in *in_data;
783 DBSTATUS *status;
784 DBORDINAL i;
786 TRACE("(%p)->(%ld, %p)\n", This, cColumns, rgColumns);
788 in_data = CoTaskMemAlloc(cColumns * sizeof(in_data[0]));
789 status = CoTaskMemAlloc(cColumns * sizeof(status[0]));
791 for(i = 0; i < cColumns; i++)
793 TRACE("%ld: wtype %04x max %08lx len %08lx\n", i, rgColumns[i].wType, rgColumns[i].cbMaxLen, rgColumns[i].cbDataLen);
794 V_VT(&in_data[i].v) = rgColumns[i].wType;
795 memcpy(&V_I1(&in_data[i].v), rgColumns[i].pData, db_type_size(rgColumns[i].wType, rgColumns[i].cbDataLen));
796 in_data[i].columnid = rgColumns[i].columnid;
797 in_data[i].data_len = rgColumns[i].cbDataLen;
798 in_data[i].status = rgColumns[i].dwStatus;
799 in_data[i].max_len = rgColumns[i].cbMaxLen;
800 in_data[i].type = rgColumns[i].wType;
801 in_data[i].precision = rgColumns[i].bPrecision;
802 in_data[i].scale = rgColumns[i].bScale;
805 hr = IWineRowServer_SetColumns(This->server, cColumns, in_data, status);
807 for(i = 0; i < cColumns; i++)
808 rgColumns[i].dwStatus = status[i];
810 CoTaskMemFree(status);
811 CoTaskMemFree(in_data);
813 return hr;
816 static const IRowChangeVtbl row_change_vtbl =
818 row_change_QueryInterface,
819 row_change_AddRef,
820 row_change_Release,
821 row_change_SetColumns
824 static HRESULT create_row_proxy(IWineRowServer *server, IUnknown **obj)
826 row_proxy *proxy;
828 TRACE("(%p, %p)\n", server, obj);
829 *obj = NULL;
831 proxy = HeapAlloc(GetProcessHeap(), 0, sizeof(*proxy));
832 if(!proxy) return E_OUTOFMEMORY;
834 proxy->IRow_iface.lpVtbl = &row_vtbl;
835 proxy->IRowChange_iface.lpVtbl = &row_change_vtbl;
836 proxy->ref = 1;
837 IWineRowServer_AddRef(server);
838 proxy->server = server;
840 *obj = (IUnknown*)&proxy->IRow_iface;
841 TRACE("returning %p\n", *obj);
842 return S_OK;
845 typedef struct
847 IRowsetLocate IRowsetLocate_iface;
848 IRowsetInfo IRowsetInfo_iface;
849 IAccessor IAccessor_iface;
851 LONG ref;
853 IWineRowServer *server;
854 } rowset_proxy;
856 static inline rowset_proxy *impl_from_IRowsetLocate(IRowsetLocate *iface)
858 return CONTAINING_RECORD(iface, rowset_proxy, IRowsetLocate_iface);
861 static inline rowset_proxy *impl_from_IRowsetInfo(IRowsetInfo *iface)
863 return CONTAINING_RECORD(iface, rowset_proxy, IRowsetInfo_iface);
866 static inline rowset_proxy *impl_from_IAccessor(IAccessor *iface)
868 return CONTAINING_RECORD(iface, rowset_proxy, IAccessor_iface);
871 static HRESULT WINAPI rowsetlocate_QueryInterface(IRowsetLocate *iface, REFIID iid, void **obj)
873 rowset_proxy *This = impl_from_IRowsetLocate(iface);
874 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(iid), obj);
876 *obj = NULL;
878 if(IsEqualIID(iid, &IID_IUnknown) ||
879 IsEqualIID(iid, &IID_IRowset) ||
880 IsEqualIID(iid, &IID_IRowsetLocate))
882 *obj = &This->IRowsetLocate_iface;
884 else if(IsEqualIID(iid, &IID_IRowsetInfo))
886 *obj = &This->IRowsetInfo_iface;
888 else if(IsEqualIID(iid, &IID_IAccessor))
890 *obj = &This->IAccessor_iface;
892 else
894 FIXME("interface %s not implemented\n", debugstr_guid(iid));
895 return E_NOINTERFACE;
898 IRowset_AddRef(iface);
899 return S_OK;
902 static ULONG WINAPI rowsetlocate_AddRef(IRowsetLocate *iface)
904 rowset_proxy *This = impl_from_IRowsetLocate(iface);
905 TRACE("(%p)\n", This);
907 return InterlockedIncrement(&This->ref);
910 static ULONG WINAPI rowsetlocate_Release(IRowsetLocate *iface)
912 rowset_proxy *This = impl_from_IRowsetLocate(iface);
913 LONG ref;
915 TRACE("(%p)\n", This);
917 ref = InterlockedDecrement(&This->ref);
918 if(ref == 0)
920 if(This->server) IWineRowServer_Release(This->server);
921 HeapFree(GetProcessHeap(), 0, This);
924 return ref;
927 static HRESULT WINAPI rowsetlocate_AddRefRows(IRowsetLocate *iface, DBCOUNTITEM cRows, const HROW rghRows[],
928 DBREFCOUNT rgRefCounts[], DBROWSTATUS rgRowStatus[])
930 rowset_proxy *This = impl_from_IRowsetLocate(iface);
931 HRESULT hr;
932 DBREFCOUNT *refs = rgRefCounts;
933 DBSTATUS *stats = rgRowStatus;
935 TRACE("(%p)->(%ld, %p, %p, %p)\n", This, cRows, rghRows, rgRefCounts, rgRowStatus);
937 if(!refs) refs = CoTaskMemAlloc(cRows * sizeof(refs[0]));
938 if(!stats) stats = CoTaskMemAlloc(cRows * sizeof(stats[0]));
940 hr = IWineRowServer_AddRefRows(This->server, cRows, rghRows, refs, stats);
942 if(refs != rgRefCounts) CoTaskMemFree(refs);
943 if(stats != rgRowStatus) CoTaskMemFree(stats);
945 return hr;
948 static HRESULT WINAPI rowsetlocate_GetData(IRowsetLocate *iface, HROW hRow, HACCESSOR hAccessor, void *pData)
950 rowset_proxy *This = impl_from_IRowsetLocate(iface);
951 HRESULT hr;
952 IAccessor *accessor;
953 DBACCESSORFLAGS flags;
954 DBCOUNTITEM count, i;
955 DBBINDING *bindings;
956 DWORD max_len = 0;
958 TRACE("(%p)->(%lx, %lx, %p)\n", This, hRow, hAccessor, pData);
960 hr = IRowsetLocate_QueryInterface(iface, &IID_IAccessor, (void**)&accessor);
961 if(FAILED(hr)) return hr;
963 hr = IAccessor_GetBindings(accessor, hAccessor, &flags, &count, &bindings);
964 IAccessor_Release(accessor);
965 if(FAILED(hr)) return hr;
967 TRACE("got %ld bindings\n", count);
968 for(i = 0; i < count; i++)
970 TRACE("%ld\tord %ld offs: val %ld len %ld stat %ld, part %x, max len %ld type %04x\n",
971 i, bindings[i].iOrdinal, bindings[i].obValue, bindings[i].obLength, bindings[i].obStatus,
972 bindings[i].dwPart, bindings[i].cbMaxLen, bindings[i].wType);
973 if(bindings[i].dwPart & DBPART_LENGTH && bindings[i].obLength >= max_len)
974 max_len = bindings[i].obLength + sizeof(DBLENGTH);
975 if(bindings[i].dwPart & DBPART_STATUS && bindings[i].obStatus >= max_len)
976 max_len = bindings[i].obStatus + sizeof(DWORD);
977 if(bindings[i].dwPart & DBPART_VALUE && bindings[i].obValue >= max_len)
978 max_len = bindings[i].obValue + db_type_size(bindings[i].wType, bindings[i].cbMaxLen);
981 TRACE("max_len %d\n", max_len);
983 CoTaskMemFree(bindings);
985 hr = IWineRowServer_GetData(This->server, hRow, hAccessor, pData, max_len);
987 return hr;
990 static HRESULT WINAPI rowsetlocate_GetNextRows(IRowsetLocate *iface, HCHAPTER hReserved, DBROWOFFSET lRowsOffset,
991 DBROWCOUNT cRows, DBCOUNTITEM *pcRowObtained, HROW **prghRows)
993 rowset_proxy *This = impl_from_IRowsetLocate(iface);
994 HRESULT hr;
995 HROW *rows = NULL;
997 TRACE("(%p)->(%08lx, %ld, %ld, %p, %p)\n", This, hReserved, lRowsOffset, cRows, pcRowObtained, prghRows);
999 hr = IWineRowServer_GetNextRows(This->server, hReserved, lRowsOffset, cRows, pcRowObtained, &rows);
1000 if(*prghRows)
1002 memcpy(*prghRows, rows, *pcRowObtained * sizeof(rows[0]));
1003 CoTaskMemFree(rows);
1005 else
1006 *prghRows = rows;
1008 return hr;
1011 static HRESULT WINAPI rowsetlocate_ReleaseRows(IRowsetLocate *iface, DBCOUNTITEM cRows, const HROW rghRows[],
1012 DBROWOPTIONS rgRowOptions[], DBREFCOUNT rgRefCounts[], DBROWSTATUS rgRowStatus[])
1014 rowset_proxy *This = impl_from_IRowsetLocate(iface);
1015 HRESULT hr;
1016 DBROWOPTIONS *options = rgRowOptions;
1017 DBREFCOUNT *refs = rgRefCounts;
1018 DBROWSTATUS *status = rgRowStatus;
1020 TRACE("(%p)->(%ld, %p, %p, %p, %p)\n", This, cRows, rghRows, rgRowOptions, rgRefCounts, rgRowStatus);
1022 if(!options)
1024 options = CoTaskMemAlloc(cRows * sizeof(options[0]));
1025 memset(options, 0, cRows * sizeof(options[0]));
1027 if(!refs) refs = CoTaskMemAlloc(cRows * sizeof(refs[0]));
1028 if(!status) status = CoTaskMemAlloc(cRows * sizeof(status[0]));
1030 hr = IWineRowServer_ReleaseRows(This->server, cRows, rghRows, options, refs, status);
1032 if(status != rgRowStatus) CoTaskMemFree(status);
1033 if(refs != rgRefCounts) CoTaskMemFree(refs);
1034 if(options != rgRowOptions) CoTaskMemFree(options);
1036 return hr;
1039 static HRESULT WINAPI rowsetlocate_RestartPosition(IRowsetLocate* iface, HCHAPTER hReserved)
1041 rowset_proxy *This = impl_from_IRowsetLocate(iface);
1043 FIXME("(%p)->(%lx): stub\n", This, hReserved);
1045 return E_NOTIMPL;
1048 static HRESULT WINAPI rowsetlocate_Compare(IRowsetLocate *iface, HCHAPTER hReserved, DBBKMARK cbBookmark1, const BYTE *pBookmark1,
1049 DBBKMARK cbBookmark2, const BYTE *pBookmark2, DBCOMPARE *pComparison)
1051 rowset_proxy *This = impl_from_IRowsetLocate(iface);
1052 FIXME("(%p)\n", This);
1053 return E_NOTIMPL;
1056 static HRESULT WINAPI rowsetlocate_GetRowsAt(IRowsetLocate *iface, HWATCHREGION hReserved1, HCHAPTER hReserved2, DBBKMARK cbBookmark,
1057 const BYTE *pBookmark, DBROWOFFSET lRowsOffset, DBROWCOUNT cRows, DBCOUNTITEM *pcRowsObtained,
1058 HROW **prghRows)
1060 rowset_proxy *This = impl_from_IRowsetLocate(iface);
1061 HRESULT hr;
1062 HROW *rows = NULL;
1064 TRACE("(%p)->(%08lx, %08lx, %ld, %p, %ld, %ld, %p, %p\n", This, hReserved1, hReserved2, cbBookmark, pBookmark, lRowsOffset, cRows,
1065 pcRowsObtained, prghRows);
1067 hr = IWineRowServer_GetRowsAt(This->server, hReserved1, hReserved2, cbBookmark, pBookmark, lRowsOffset, cRows, pcRowsObtained, &rows);
1069 if(*prghRows)
1071 memcpy(*prghRows, rows, *pcRowsObtained * sizeof(rows[0]));
1072 CoTaskMemFree(rows);
1074 else
1075 *prghRows = rows;
1077 return hr;
1080 static HRESULT WINAPI rowsetlocate_GetRowsByBookmark(IRowsetLocate *iface, HCHAPTER hReserved, DBCOUNTITEM cRows, const DBBKMARK rgcbBookmarks[],
1081 const BYTE * rgpBookmarks[], HROW rghRows[], DBROWSTATUS rgRowStatus[])
1083 rowset_proxy *This = impl_from_IRowsetLocate(iface);
1084 FIXME("(%p)\n", This);
1085 return E_NOTIMPL;
1088 static HRESULT WINAPI rowsetlocate_Hash(IRowsetLocate *iface, HCHAPTER hReserved, DBBKMARK cBookmarks, const DBBKMARK rgcbBookmarks[],
1089 const BYTE * rgpBookmarks[], DBHASHVALUE rgHashedValues[], DBROWSTATUS rgBookmarkStatus[])
1091 rowset_proxy *This = impl_from_IRowsetLocate(iface);
1092 FIXME("(%p)\n", This);
1093 return E_NOTIMPL;
1096 static const IRowsetLocateVtbl rowsetlocate_vtbl =
1098 rowsetlocate_QueryInterface,
1099 rowsetlocate_AddRef,
1100 rowsetlocate_Release,
1101 rowsetlocate_AddRefRows,
1102 rowsetlocate_GetData,
1103 rowsetlocate_GetNextRows,
1104 rowsetlocate_ReleaseRows,
1105 rowsetlocate_RestartPosition,
1106 rowsetlocate_Compare,
1107 rowsetlocate_GetRowsAt,
1108 rowsetlocate_GetRowsByBookmark,
1109 rowsetlocate_Hash
1112 static HRESULT WINAPI rowsetinfo_QueryInterface(IRowsetInfo *iface, REFIID iid, void **obj)
1114 rowset_proxy *This = impl_from_IRowsetInfo(iface);
1115 return IUnknown_QueryInterface((IUnknown *)This, iid, obj);
1118 static ULONG WINAPI rowsetinfo_AddRef(IRowsetInfo *iface)
1120 rowset_proxy *This = impl_from_IRowsetInfo(iface);
1121 return IUnknown_AddRef((IUnknown *)This);
1124 static ULONG WINAPI rowsetinfo_Release(IRowsetInfo *iface)
1126 rowset_proxy *This = impl_from_IRowsetInfo(iface);
1127 return IUnknown_Release((IUnknown *)This);
1130 static HRESULT WINAPI rowsetinfo_GetProperties(IRowsetInfo *iface, const ULONG cPropertyIDSets,
1131 const DBPROPIDSET rgPropertyIDSets[], ULONG *pcPropertySets,
1132 DBPROPSET **prgPropertySets)
1134 rowset_proxy *This = impl_from_IRowsetInfo(iface);
1135 HRESULT hr;
1137 TRACE("(%p)->(%d, %p, %p, %p)\n", This, cPropertyIDSets, rgPropertyIDSets, pcPropertySets, prgPropertySets);
1139 hr = IWineRowServer_GetProperties(This->server, cPropertyIDSets, rgPropertyIDSets, pcPropertySets, prgPropertySets);
1141 return hr;
1144 static HRESULT WINAPI rowsetinfo_GetReferencedRowset(IRowsetInfo *iface, DBORDINAL iOrdinal, REFIID riid,
1145 IUnknown **ppReferencedRowset)
1147 rowset_proxy *This = impl_from_IRowsetInfo(iface);
1148 FIXME("(%p)\n", This);
1149 return E_NOTIMPL;
1152 static HRESULT WINAPI rowsetinfo_GetSpecification(IRowsetInfo *iface, REFIID riid, IUnknown **ppSpecification)
1154 rowset_proxy *This = impl_from_IRowsetInfo(iface);
1155 FIXME("(%p)\n", This);
1156 return E_NOTIMPL;
1159 static const IRowsetInfoVtbl rowsetinfo_vtbl =
1161 rowsetinfo_QueryInterface,
1162 rowsetinfo_AddRef,
1163 rowsetinfo_Release,
1164 rowsetinfo_GetProperties,
1165 rowsetinfo_GetReferencedRowset,
1166 rowsetinfo_GetSpecification
1169 static HRESULT WINAPI accessor_QueryInterface(IAccessor *iface, REFIID iid, void **obj)
1171 rowset_proxy *This = impl_from_IAccessor(iface);
1172 return IUnknown_QueryInterface((IUnknown *)This, iid, obj);
1175 static ULONG WINAPI accessor_AddRef(IAccessor *iface)
1177 rowset_proxy *This = impl_from_IAccessor(iface);
1178 return IUnknown_AddRef((IUnknown *)This);
1181 static ULONG WINAPI accessor_Release(IAccessor *iface)
1183 rowset_proxy *This = impl_from_IAccessor(iface);
1184 return IUnknown_Release((IUnknown *)This);
1187 static HRESULT WINAPI accessor_AddRefAccessor(IAccessor *iface, HACCESSOR hAccessor, DBREFCOUNT *pcRefCount)
1189 rowset_proxy *This = impl_from_IAccessor(iface);
1190 FIXME("(%p)\n", This);
1191 return E_NOTIMPL;
1194 static HRESULT WINAPI accessor_CreateAccessor(IAccessor *iface, DBACCESSORFLAGS dwAccessorFlags, DBCOUNTITEM cBindings,
1195 const DBBINDING rgBindings[], DBLENGTH cbRowSize, HACCESSOR *phAccessor,
1196 DBBINDSTATUS rgStatus[])
1198 rowset_proxy *This = impl_from_IAccessor(iface);
1199 HRESULT hr;
1200 DBBINDSTATUS *status;
1202 TRACE("(%p)->(%08x, %ld, %p, %ld, %p, %p)\n", This, dwAccessorFlags, cBindings, rgBindings, cbRowSize, phAccessor, rgStatus);
1204 if(!rgStatus) status = CoTaskMemAlloc(cBindings * sizeof(status[0]));
1205 else status = rgStatus;
1207 hr = IWineRowServer_CreateAccessor(This->server, dwAccessorFlags, cBindings, rgBindings, cbRowSize, phAccessor, status);
1209 if(!rgStatus) CoTaskMemFree(status);
1211 return hr;
1214 static HRESULT WINAPI accessor_GetBindings(IAccessor *iface, HACCESSOR hAccessor, DBACCESSORFLAGS *pdwAccessorFlags,
1215 DBCOUNTITEM *pcBindings, DBBINDING **prgBindings)
1217 rowset_proxy *This = impl_from_IAccessor(iface);
1218 HRESULT hr;
1220 TRACE("(%p)->(%08lx, %p, %p, %p)\n", This, hAccessor, pdwAccessorFlags, pcBindings, prgBindings);
1222 hr = IWineRowServer_GetBindings(This->server, hAccessor, pdwAccessorFlags, pcBindings, prgBindings);
1224 return hr;
1227 static HRESULT WINAPI accessor_ReleaseAccessor(IAccessor *iface, HACCESSOR hAccessor, DBREFCOUNT *pcRefCount)
1229 rowset_proxy *This = impl_from_IAccessor(iface);
1230 HRESULT hr;
1231 DBREFCOUNT ref;
1233 TRACE("(%p)->(%08lx, %p)\n", This, hAccessor, pcRefCount);
1235 hr = IWineRowServer_ReleaseAccessor(This->server, hAccessor, &ref);
1236 if(pcRefCount) *pcRefCount = ref;
1237 return hr;
1240 static const IAccessorVtbl accessor_vtbl =
1242 accessor_QueryInterface,
1243 accessor_AddRef,
1244 accessor_Release,
1245 accessor_AddRefAccessor,
1246 accessor_CreateAccessor,
1247 accessor_GetBindings,
1248 accessor_ReleaseAccessor
1251 static HRESULT create_rowset_proxy(IWineRowServer *server, IUnknown **obj)
1253 rowset_proxy *proxy;
1255 TRACE("(%p, %p)\n", server, obj);
1256 *obj = NULL;
1258 proxy = HeapAlloc(GetProcessHeap(), 0, sizeof(*proxy));
1259 if(!proxy) return E_OUTOFMEMORY;
1261 proxy->IRowsetLocate_iface.lpVtbl = &rowsetlocate_vtbl;
1262 proxy->IRowsetInfo_iface.lpVtbl = &rowsetinfo_vtbl;
1263 proxy->IAccessor_iface.lpVtbl = &accessor_vtbl;
1264 proxy->ref = 1;
1265 IWineRowServer_AddRef(server);
1266 proxy->server = server;
1268 *obj = (IUnknown *)&proxy->IRowsetLocate_iface;
1269 TRACE("returning %p\n", *obj);
1270 return S_OK;
1273 static HRESULT create_proxy(IWineRowServer *server, const CLSID *class, IUnknown **obj)
1275 *obj = NULL;
1277 if(IsEqualGUID(class, &CLSID_wine_row_proxy))
1278 return create_row_proxy(server, obj);
1279 else if(IsEqualGUID(class, &CLSID_wine_rowset_proxy))
1280 return create_rowset_proxy(server, obj);
1281 else
1282 FIXME("Unhandled proxy class %s\n", debugstr_guid(class));
1283 return E_NOTIMPL;
1286 /* Marshal impl */
1288 typedef struct
1290 IMarshal IMarshal_iface;
1292 LONG ref;
1293 CLSID unmarshal_class;
1294 IUnknown *outer;
1295 } marshal;
1297 static inline marshal *impl_from_IMarshal(IMarshal *iface)
1299 return CONTAINING_RECORD(iface, marshal, IMarshal_iface);
1302 static HRESULT WINAPI marshal_QueryInterface(IMarshal *iface, REFIID iid, void **obj)
1304 marshal *This = impl_from_IMarshal(iface);
1305 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(iid), obj);
1307 if(IsEqualIID(iid, &IID_IUnknown) ||
1308 IsEqualIID(iid, &IID_IMarshal))
1310 *obj = iface;
1312 else
1314 FIXME("interface %s not implemented\n", debugstr_guid(iid));
1315 *obj = NULL;
1316 return E_NOINTERFACE;
1319 IMarshal_AddRef(iface);
1320 return S_OK;
1323 static ULONG WINAPI marshal_AddRef(IMarshal *iface)
1325 marshal *This = impl_from_IMarshal(iface);
1326 TRACE("(%p)\n", This);
1327 return InterlockedIncrement(&This->ref);
1330 static ULONG WINAPI marshal_Release(IMarshal *iface)
1332 marshal *This = impl_from_IMarshal(iface);
1333 LONG ref;
1335 TRACE("(%p)\n", This);
1337 ref = InterlockedDecrement(&This->ref);
1338 if(ref == 0)
1340 HeapFree(GetProcessHeap(), 0, This);
1343 return ref;
1346 static HRESULT WINAPI marshal_GetUnmarshalClass(IMarshal *iface, REFIID iid, void *obj,
1347 DWORD dwDestContext, void *pvDestContext,
1348 DWORD mshlflags, CLSID *clsid)
1350 marshal *This = impl_from_IMarshal(iface);
1351 TRACE("(%p)->(%s, %p, %08x, %p, %08x, %p)\n", This, debugstr_guid(iid), obj, dwDestContext,
1352 pvDestContext, mshlflags, clsid);
1354 *clsid = This->unmarshal_class;
1355 return S_OK;
1358 static HRESULT WINAPI marshal_GetMarshalSizeMax(IMarshal *iface, REFIID iid, void *obj,
1359 DWORD dwDestContext, void *pvDestContext,
1360 DWORD mshlflags, DWORD *size)
1362 marshal *This = impl_from_IMarshal(iface);
1363 TRACE("(%p)->(%s, %p, %08x, %p, %08x, %p)\n", This, debugstr_guid(iid), obj, dwDestContext,
1364 pvDestContext, mshlflags, size);
1366 return CoGetMarshalSizeMax(size, &IID_IWineRowServer, This->outer, dwDestContext, pvDestContext,
1367 mshlflags);
1370 static HRESULT WINAPI marshal_MarshalInterface(IMarshal *iface, IStream *stream, REFIID iid,
1371 void *obj, DWORD dwDestContext, void *pvDestContext,
1372 DWORD mshlflags)
1374 marshal *This = impl_from_IMarshal(iface);
1375 TRACE("(%p)->(%p, %s, %p, %08x, %p, %08x)\n", This, stream, debugstr_guid(iid), obj, dwDestContext,
1376 pvDestContext, mshlflags);
1378 return CoMarshalInterface(stream, &IID_IWineRowServer, This->outer, dwDestContext, pvDestContext, mshlflags);
1381 static HRESULT WINAPI marshal_UnmarshalInterface(IMarshal *iface, IStream *stream,
1382 REFIID iid, void **obj)
1384 marshal *This = impl_from_IMarshal(iface);
1385 HRESULT hr;
1386 IWineRowServer *server;
1387 IUnknown *proxy;
1389 TRACE("(%p)->(%p, %s, %p)\n", This, stream, debugstr_guid(iid), obj);
1390 *obj = NULL;
1392 hr = CoUnmarshalInterface(stream, &IID_IWineRowServer, (void**)&server);
1393 if(SUCCEEDED(hr))
1395 hr = create_proxy(server, &This->unmarshal_class, &proxy);
1396 if(SUCCEEDED(hr))
1398 hr = IUnknown_QueryInterface(proxy, iid, obj);
1399 IUnknown_Release(proxy);
1401 IWineRowServer_Release(server);
1404 TRACE("returning %p\n", *obj);
1405 return hr;
1408 static HRESULT WINAPI marshal_ReleaseMarshalData(IMarshal *iface, IStream *stream)
1410 marshal *This = impl_from_IMarshal(iface);
1411 TRACE("(%p)->(%p)\n", This, stream);
1412 return CoReleaseMarshalData(stream);
1415 static HRESULT WINAPI marshal_DisconnectObject(IMarshal *iface, DWORD dwReserved)
1417 marshal *This = impl_from_IMarshal(iface);
1418 FIXME("(%p)->(%08x)\n", This, dwReserved);
1420 return E_NOTIMPL;
1423 static const IMarshalVtbl marshal_vtbl =
1425 marshal_QueryInterface,
1426 marshal_AddRef,
1427 marshal_Release,
1428 marshal_GetUnmarshalClass,
1429 marshal_GetMarshalSizeMax,
1430 marshal_MarshalInterface,
1431 marshal_UnmarshalInterface,
1432 marshal_ReleaseMarshalData,
1433 marshal_DisconnectObject
1436 static HRESULT create_marshal(IUnknown *outer, const CLSID *class, void **obj)
1438 marshal *marshal;
1440 TRACE("(%p, %p)\n", outer, obj);
1441 *obj = NULL;
1443 marshal = HeapAlloc(GetProcessHeap(), 0, sizeof(*marshal));
1444 if(!marshal) return E_OUTOFMEMORY;
1446 marshal->unmarshal_class = *class;
1447 marshal->outer = outer; /* don't ref outer unk */
1448 marshal->IMarshal_iface.lpVtbl = &marshal_vtbl;
1449 marshal->ref = 1;
1451 *obj = &marshal->IMarshal_iface;
1452 TRACE("returning %p\n", *obj);
1453 return S_OK;
1456 HRESULT create_row_marshal(IUnknown *outer, void **obj)
1458 TRACE("(%p, %p)\n", outer, obj);
1459 return create_marshal(outer, &CLSID_wine_row_proxy, obj);
1462 HRESULT create_rowset_marshal(IUnknown *outer, void **obj)
1464 TRACE("(%p, %p)\n", outer, obj);
1465 return create_marshal(outer, &CLSID_wine_rowset_proxy, obj);