msdaps: Add server side stubs for IRowsetLocate.
[wine/hramrach.git] / dlls / msdaps / row_server.c
blob817b1e923ae047abfc09a92823fa105d2027dca6
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 const IWineRowServerVtbl *vtbl;
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 (server *)((char*)iface - FIELD_OFFSET(server, vtbl));
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)->(%d, %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("%d:\tmax_len %d 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);
223 FIXME("(%p)->(%p, %p, %s, %08x, %s, %p): stub\n", This, pUnkOuter, pColumnID, debugstr_guid(rguidColumnType),
224 dwBindFlags, debugstr_guid(riid), ppUnk);
225 return E_NOTIMPL;
228 static HRESULT WINAPI server_SetColumns(IWineRowServer* iface, DBORDINAL num_cols,
229 wine_setcolumns_in *in_data, DBSTATUS *status)
231 server *This = impl_from_IWineRowServer(iface);
232 FIXME("(%p)->(%d, %p, %p): stub\n", This, num_cols, in_data, status);
233 return E_NOTIMPL;
236 static HRESULT WINAPI server_AddRefRows(IWineRowServer* iface, DBCOUNTITEM cRows,
237 const HROW rghRows[], DBREFCOUNT rgRefCounts[],
238 DBROWSTATUS rgRowStatus[])
240 server *This = impl_from_IWineRowServer(iface);
241 IRowset *rowset;
242 HRESULT hr;
244 TRACE("(%p)->(%d, %p, %p, %p)\n", This, cRows, rghRows, rgRefCounts, rgRowStatus);
246 hr = IUnknown_QueryInterface(This->inner_unk, &IID_IRowset, (void**)&rowset);
247 if(FAILED(hr)) return hr;
249 hr = IRowset_AddRefRows(rowset, cRows, rghRows, rgRefCounts, rgRowStatus);
251 IRowset_Release(rowset);
252 TRACE("returning %08x\n", hr);
253 return hr;
256 static HRESULT WINAPI server_GetData(IWineRowServer* iface, HROW hRow,
257 HACCESSOR hAccessor, BYTE *pData, DWORD size)
259 server *This = impl_from_IWineRowServer(iface);
260 FIXME("(%p)->(%08lx, %08lx, %p, %d): stub\n", This, hRow, hAccessor, pData, size);
261 return E_NOTIMPL;
264 static HRESULT WINAPI server_GetNextRows(IWineRowServer* iface, HCHAPTER hReserved, DBROWOFFSET lRowsOffset,
265 DBROWCOUNT cRows, DBCOUNTITEM *pcRowObtained, HROW **prghRows)
267 server *This = impl_from_IWineRowServer(iface);
268 IRowset *rowset;
269 HRESULT hr;
271 TRACE("(%p)->(%08lx, %d, %d, %p, %p)\n", This, hReserved, lRowsOffset, cRows, pcRowObtained, prghRows);
273 hr = IUnknown_QueryInterface(This->inner_unk, &IID_IRowset, (void**)&rowset);
274 if(FAILED(hr)) return hr;
276 *prghRows = NULL;
278 hr = IRowset_GetNextRows(rowset, hReserved, lRowsOffset, cRows, pcRowObtained, prghRows);
279 IRowset_Release(rowset);
280 TRACE("returning %08x, got %d rows\n", hr, *pcRowObtained);
281 return hr;
284 static HRESULT WINAPI server_ReleaseRows(IWineRowServer* iface, DBCOUNTITEM cRows, const HROW rghRows[],
285 DBROWOPTIONS rgRowOptions[], DBREFCOUNT rgRefCounts[], DBROWSTATUS rgRowStatus[])
287 server *This = impl_from_IWineRowServer(iface);
288 IRowset *rowset;
289 HRESULT hr;
291 TRACE("(%p)->(%d, %p, %p, %p, %p)\n", This, cRows, rghRows, rgRowOptions, rgRefCounts, rgRowStatus);
293 hr = IUnknown_QueryInterface(This->inner_unk, &IID_IRowset, (void**)&rowset);
294 if(FAILED(hr)) return hr;
296 hr = IRowset_ReleaseRows(rowset, cRows, rghRows, rgRowOptions, rgRefCounts, rgRowStatus);
297 IRowset_Release(rowset);
299 TRACE("returning %08x\n", hr);
300 return hr;
303 static HRESULT WINAPI server_RestartPosition(IWineRowServer* iface, HCHAPTER hReserved)
305 server *This = impl_from_IWineRowServer(iface);
306 FIXME("(%p)->(%08lx): stub\n", This, hReserved);
307 return E_NOTIMPL;
310 static HRESULT WINAPI server_Compare(IWineRowServer *iface, HCHAPTER hReserved, DBBKMARK cbBookmark1,
311 const BYTE *pBookmark1, DBBKMARK cbBookmark2, const BYTE *pBookmark2,
312 DBCOMPARE *pComparison)
314 server *This = impl_from_IWineRowServer(iface);
315 FIXME("(%p): stub\n", This);
316 return E_NOTIMPL;
319 static HRESULT WINAPI server_GetRowsAt(IWineRowServer *iface, HWATCHREGION hReserved1, HCHAPTER hReserved2,
320 DBBKMARK cbBookmark, const BYTE *pBookmark, DBROWOFFSET lRowsOffset,
321 DBROWCOUNT cRows, DBCOUNTITEM *pcRowsObtained, HROW **prghRows)
323 server *This = impl_from_IWineRowServer(iface);
325 FIXME("(%p)->(%08lx, %08lx, %d, %p, %d, %d, %p, %p): stub\n", This, hReserved1, hReserved2, cbBookmark, pBookmark,
326 lRowsOffset, cRows, pcRowsObtained, prghRows);
328 return E_NOTIMPL;
331 static HRESULT WINAPI server_GetRowsByBookmark(IWineRowServer *iface, HCHAPTER hReserved, DBCOUNTITEM cRows,
332 const DBBKMARK rgcbBookmarks[], const BYTE * rgpBookmarks[],
333 HROW rghRows[], DBROWSTATUS rgRowStatus[])
335 server *This = impl_from_IWineRowServer(iface);
336 FIXME("(%p): stub\n", This);
337 return E_NOTIMPL;
340 static HRESULT WINAPI server_Hash(IWineRowServer *iface, HCHAPTER hReserved, DBBKMARK cBookmarks,
341 const DBBKMARK rgcbBookmarks[], const BYTE * rgpBookmarks[],
342 DBHASHVALUE rgHashedValues[], DBROWSTATUS rgBookmarkStatus[])
344 server *This = impl_from_IWineRowServer(iface);
345 FIXME("(%p): stub\n", This);
346 return E_NOTIMPL;
349 static const IWineRowServerVtbl server_vtbl =
351 server_QueryInterface,
352 server_AddRef,
353 server_Release,
354 server_SetInnerUnk,
355 server_GetMarshal,
356 server_GetColumns,
357 server_GetSourceRowset,
358 server_Open,
359 server_SetColumns,
360 server_AddRefRows,
361 server_GetData,
362 server_GetNextRows,
363 server_ReleaseRows,
364 server_RestartPosition,
365 server_Compare,
366 server_GetRowsAt,
367 server_GetRowsByBookmark,
368 server_Hash
371 static HRESULT create_server(IUnknown *outer, const CLSID *class, void **obj)
373 server *server;
374 TRACE("(%p, %s, %p)\n", outer, debugstr_guid(class), obj);
376 *obj = NULL;
378 server = HeapAlloc(GetProcessHeap(), 0, sizeof(*server));
379 if(!server) return E_OUTOFMEMORY;
381 server->vtbl = &server_vtbl;
382 server->ref = 1;
383 server->class = *class;
384 server->inner_unk = NULL;
385 if(IsEqualGUID(class, &CLSID_wine_row_server))
386 create_row_marshal((IUnknown*)server, (void**)&server->marshal);
387 else if(IsEqualGUID(class, &CLSID_wine_rowset_server))
388 create_rowset_marshal((IUnknown*)server, (void**)&server->marshal);
389 else
390 ERR("create_server called with class %s\n", debugstr_guid(class));
392 *obj = server;
393 return S_OK;
396 HRESULT create_row_server(IUnknown *outer, void **obj)
398 return create_server(outer, &CLSID_wine_row_server, obj);
401 HRESULT create_rowset_server(IUnknown *outer, void **obj)
403 return create_server(outer, &CLSID_wine_rowset_server, obj);
406 typedef struct
408 const IRowVtbl *row_vtbl;
409 const IRowChangeVtbl *row_change_vtbl;
411 LONG ref;
413 IWineRowServer *server;
414 } row_proxy;
416 static inline row_proxy *impl_from_IRow(IRow *iface)
418 return (row_proxy *)((char*)iface - FIELD_OFFSET(row_proxy, row_vtbl));
421 static inline row_proxy *impl_from_IRowChange(IRowChange *iface)
423 return (row_proxy *)((char*)iface - FIELD_OFFSET(row_proxy, row_change_vtbl));
426 static HRESULT WINAPI row_QueryInterface(IRow *iface, REFIID iid, void **obj)
428 row_proxy *This = impl_from_IRow(iface);
429 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(iid), obj);
431 if(IsEqualIID(iid, &IID_IUnknown) ||
432 IsEqualIID(iid, &IID_IRow))
434 *obj = &This->row_vtbl;
436 else if(IsEqualIID(iid, &IID_IRowChange))
438 *obj = &This->row_change_vtbl;
440 else
442 FIXME("interface %s not implemented\n", debugstr_guid(iid));
443 return E_NOINTERFACE;
446 IRow_AddRef(iface);
447 return S_OK;
450 static ULONG WINAPI row_AddRef(IRow *iface)
452 row_proxy *This = impl_from_IRow(iface);
453 TRACE("(%p)\n", This);
455 return InterlockedIncrement(&This->ref);
458 static ULONG WINAPI row_Release(IRow *iface)
460 row_proxy *This = impl_from_IRow(iface);
461 LONG ref;
463 TRACE("(%p)\n", This);
465 ref = InterlockedDecrement(&This->ref);
466 if(ref == 0)
468 if(This->server) IWineRowServer_Release(This->server);
469 HeapFree(GetProcessHeap(), 0, This);
472 return ref;
475 static HRESULT WINAPI row_GetColumns(IRow* iface, DBORDINAL cColumns, DBCOLUMNACCESS rgColumns[])
477 row_proxy *This = impl_from_IRow(iface);
478 DBORDINAL i;
479 wine_getcolumns_in *in_data;
480 wine_getcolumns_out *out_data;
481 HRESULT hr;
483 TRACE("(%p)->(%d, %p)\n", This, cColumns, rgColumns);
485 in_data = CoTaskMemAlloc(cColumns * sizeof(in_data[0]));
486 out_data = CoTaskMemAlloc(cColumns * sizeof(out_data[0]));
488 for(i = 0; i < cColumns; i++)
490 TRACE("%d:\tdata %p data_len %d status %08x max_len %d type %04x\n", i, rgColumns[i].pData,
491 rgColumns[i].cbDataLen, rgColumns[i].dwStatus, rgColumns[i].cbMaxLen, rgColumns[i].wType);
492 in_data[i].columnid = rgColumns[i].columnid;
493 in_data[i].max_len = rgColumns[i].cbMaxLen;
494 in_data[i].type = rgColumns[i].wType;
495 in_data[i].precision = rgColumns[i].bPrecision;
496 in_data[i].scale = rgColumns[i].bScale;
499 hr = IWineRowServer_GetColumns(This->server, cColumns, in_data, out_data);
501 for(i = 0; i < cColumns; i++)
503 rgColumns[i].cbDataLen = out_data[i].data_len;
504 rgColumns[i].dwStatus = out_data[i].status;
505 if(rgColumns[i].dwStatus == DBSTATUS_S_OK)
506 memcpy(rgColumns[i].pData, &V_I1(&out_data[i].v), out_data[i].data_len);
509 CoTaskMemFree(out_data);
510 CoTaskMemFree(in_data);
511 return hr;
514 static HRESULT WINAPI row_GetSourceRowset(IRow* iface, REFIID riid, IUnknown **ppRowset,
515 HROW *phRow)
517 row_proxy *This = impl_from_IRow(iface);
519 FIXME("(%p)->(%s, %p, %p): stub\n", This, debugstr_guid(riid), ppRowset, phRow);
521 return E_NOTIMPL;
524 static HRESULT WINAPI row_Open(IRow* iface, IUnknown *pUnkOuter,
525 DBID *pColumnID, REFGUID rguidColumnType,
526 DWORD dwBindFlags, REFIID riid, IUnknown **ppUnk)
528 row_proxy *This = impl_from_IRow(iface);
530 FIXME("(%p)->(%p, %p, %s, %08x, %s, %p): stub\n", This, pUnkOuter, pColumnID, debugstr_guid(rguidColumnType),
531 dwBindFlags, debugstr_guid(riid), ppUnk);
533 return E_NOTIMPL;
536 static const IRowVtbl row_vtbl =
538 row_QueryInterface,
539 row_AddRef,
540 row_Release,
541 row_GetColumns,
542 row_GetSourceRowset,
543 row_Open
546 static HRESULT WINAPI row_change_QueryInterface(IRowChange *iface, REFIID iid, void **obj)
548 row_proxy *This = impl_from_IRowChange(iface);
549 return IUnknown_QueryInterface((IUnknown *)This, iid, obj);
552 static ULONG WINAPI row_change_AddRef(IRowChange *iface)
554 row_proxy *This = impl_from_IRowChange(iface);
555 return IUnknown_AddRef((IUnknown*)This);
558 static ULONG WINAPI row_change_Release(IRowChange *iface)
560 row_proxy *This = impl_from_IRowChange(iface);
561 return IUnknown_Release((IUnknown*)This);
564 static HRESULT WINAPI row_change_SetColumns(IRowChange *iface, DBORDINAL cColumns,
565 DBCOLUMNACCESS rgColumns[])
567 row_proxy *This = impl_from_IRowChange(iface);
568 FIXME("(%p)->(%d, %p)\n", This, cColumns, rgColumns);
569 return E_NOTIMPL;
572 static const IRowChangeVtbl row_change_vtbl =
574 row_change_QueryInterface,
575 row_change_AddRef,
576 row_change_Release,
577 row_change_SetColumns
580 static HRESULT create_row_proxy(IWineRowServer *server, IUnknown **obj)
582 row_proxy *proxy;
584 TRACE("(%p, %p)\n", server, obj);
585 *obj = NULL;
587 proxy = HeapAlloc(GetProcessHeap(), 0, sizeof(*proxy));
588 if(!proxy) return E_OUTOFMEMORY;
590 proxy->row_vtbl = &row_vtbl;
591 proxy->row_change_vtbl = &row_change_vtbl;
592 proxy->ref = 1;
593 IWineRowServer_AddRef(server);
594 proxy->server = server;
596 *obj = (IUnknown*)&proxy->row_vtbl;
597 TRACE("returing %p\n", *obj);
598 return S_OK;
601 typedef struct
603 const IRowsetVtbl *rowset_vtbl;
605 LONG ref;
607 IWineRowServer *server;
608 } rowset_proxy;
610 static inline rowset_proxy *impl_from_IRowset(IRowset *iface)
612 return (rowset_proxy *)((char*)iface - FIELD_OFFSET(rowset_proxy, rowset_vtbl));
615 static HRESULT WINAPI rowset_QueryInterface(IRowset *iface, REFIID iid, void **obj)
617 rowset_proxy *This = impl_from_IRowset(iface);
618 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(iid), obj);
620 *obj = NULL;
622 if(IsEqualIID(iid, &IID_IUnknown) ||
623 IsEqualIID(iid, &IID_IRowset))
625 *obj = &This->rowset_vtbl;
627 else
629 FIXME("interface %s not implemented\n", debugstr_guid(iid));
630 return E_NOINTERFACE;
633 IRowset_AddRef(iface);
634 return S_OK;
637 static ULONG WINAPI rowset_AddRef(IRowset *iface)
639 rowset_proxy *This = impl_from_IRowset(iface);
640 TRACE("(%p)\n", This);
642 return InterlockedIncrement(&This->ref);
645 static ULONG WINAPI rowset_Release(IRowset *iface)
647 rowset_proxy *This = impl_from_IRowset(iface);
648 LONG ref;
650 TRACE("(%p)\n", This);
652 ref = InterlockedDecrement(&This->ref);
653 if(ref == 0)
655 if(This->server) IWineRowServer_Release(This->server);
656 HeapFree(GetProcessHeap(), 0, This);
659 return ref;
662 static HRESULT WINAPI rowset_AddRefRows(IRowset *iface, DBCOUNTITEM cRows, const HROW rghRows[],
663 DBREFCOUNT rgRefCounts[], DBROWSTATUS rgRowStatus[])
665 rowset_proxy *This = impl_from_IRowset(iface);
666 HRESULT hr;
667 DBREFCOUNT *refs = rgRefCounts;
668 DBSTATUS *stats = rgRowStatus;
670 TRACE("(%p)->(%d, %p, %p, %p)\n", This, cRows, rghRows, rgRefCounts, rgRowStatus);
672 if(!refs) refs = CoTaskMemAlloc(cRows * sizeof(refs[0]));
673 if(!stats) stats = CoTaskMemAlloc(cRows * sizeof(stats[0]));
675 hr = IWineRowServer_AddRefRows(This->server, cRows, rghRows, refs, stats);
677 if(refs != rgRefCounts) CoTaskMemFree(refs);
678 if(stats != rgRowStatus) CoTaskMemFree(stats);
680 return hr;
683 static HRESULT WINAPI rowset_GetData(IRowset *iface, HROW hRow, HACCESSOR hAccessor, void *pData)
685 rowset_proxy *This = impl_from_IRowset(iface);
687 FIXME("(%p)->(%lx, %lx, %p): stub\n", This, hRow, hAccessor, pData);
689 return E_NOTIMPL;
692 static HRESULT WINAPI rowset_GetNextRows(IRowset *iface, HCHAPTER hReserved, DBROWOFFSET lRowsOffset,
693 DBROWCOUNT cRows, DBCOUNTITEM *pcRowObtained, HROW **prghRows)
695 rowset_proxy *This = impl_from_IRowset(iface);
696 HRESULT hr;
697 HROW *rows = NULL;
699 TRACE("(%p)->(%08lx, %d, %d, %p, %p)\n", This, hReserved, lRowsOffset, cRows, pcRowObtained, prghRows);
701 hr = IWineRowServer_GetNextRows(This->server, hReserved, lRowsOffset, cRows, pcRowObtained, &rows);
702 if(*prghRows)
704 memcpy(*prghRows, rows, *pcRowObtained * sizeof(rows[0]));
705 CoTaskMemFree(rows);
707 else
708 *prghRows = rows;
710 return hr;
713 static HRESULT WINAPI rowset_ReleaseRows(IRowset *iface, DBCOUNTITEM cRows, const HROW rghRows[],
714 DBROWOPTIONS rgRowOptions[], DBREFCOUNT rgRefCounts[], DBROWSTATUS rgRowStatus[])
716 rowset_proxy *This = impl_from_IRowset(iface);
717 HRESULT hr;
718 DBROWOPTIONS *options = rgRowOptions;
719 DBREFCOUNT *refs = rgRefCounts;
720 DBROWSTATUS *status = rgRowStatus;
722 TRACE("(%p)->(%d, %p, %p, %p, %p)\n", This, cRows, rghRows, rgRowOptions, rgRefCounts, rgRowStatus);
724 if(!options)
726 options = CoTaskMemAlloc(cRows * sizeof(options[0]));
727 memset(options, 0, cRows * sizeof(options[0]));
729 if(!refs) refs = CoTaskMemAlloc(cRows * sizeof(refs[0]));
730 if(!status) status = CoTaskMemAlloc(cRows * sizeof(status[0]));
732 hr = IWineRowServer_ReleaseRows(This->server, cRows, rghRows, options, refs, status);
734 if(status != rgRowStatus) CoTaskMemFree(status);
735 if(refs != rgRefCounts) CoTaskMemFree(refs);
736 if(options != rgRowOptions) CoTaskMemFree(options);
738 return hr;
741 static HRESULT WINAPI rowset_RestartPosition(IRowset* iface, HCHAPTER hReserved)
743 rowset_proxy *This = impl_from_IRowset(iface);
745 FIXME("(%p)->(%lx): stub\n", This, hReserved);
747 return E_NOTIMPL;
750 static const IRowsetVtbl rowset_vtbl =
752 rowset_QueryInterface,
753 rowset_AddRef,
754 rowset_Release,
755 rowset_AddRefRows,
756 rowset_GetData,
757 rowset_GetNextRows,
758 rowset_ReleaseRows,
759 rowset_RestartPosition
762 HRESULT create_rowset_proxy(IWineRowServer *server, IUnknown **obj)
764 rowset_proxy *proxy;
766 TRACE("(%p, %p)\n", server, obj);
767 *obj = NULL;
769 proxy = HeapAlloc(GetProcessHeap(), 0, sizeof(*proxy));
770 if(!proxy) return E_OUTOFMEMORY;
772 proxy->rowset_vtbl = &rowset_vtbl;
773 proxy->ref = 1;
774 IWineRowServer_AddRef(server);
775 proxy->server = server;
777 *obj = (IUnknown *)&proxy->rowset_vtbl;
778 TRACE("returing %p\n", *obj);
779 return S_OK;
782 static HRESULT create_proxy(IWineRowServer *server, const CLSID *class, IUnknown **obj)
784 *obj = NULL;
786 if(IsEqualGUID(class, &CLSID_wine_row_proxy))
787 return create_row_proxy(server, obj);
788 else if(IsEqualGUID(class, &CLSID_wine_rowset_proxy))
789 return create_rowset_proxy(server, obj);
790 else
791 FIXME("Unhandled proxy class %s\n", debugstr_guid(class));
792 return E_NOTIMPL;
795 /* Marshal impl */
797 typedef struct
799 const IMarshalVtbl *marshal_vtbl;
801 LONG ref;
802 CLSID unmarshal_class;
803 IUnknown *outer;
804 } marshal;
806 static inline marshal *impl_from_IMarshal(IMarshal *iface)
808 return (marshal *)((char*)iface - FIELD_OFFSET(marshal, marshal_vtbl));
811 static HRESULT WINAPI marshal_QueryInterface(IMarshal *iface, REFIID iid, void **obj)
813 marshal *This = impl_from_IMarshal(iface);
814 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(iid), obj);
816 if(IsEqualIID(iid, &IID_IUnknown) ||
817 IsEqualIID(iid, &IID_IMarshal))
819 *obj = iface;
821 else
823 FIXME("interface %s not implemented\n", debugstr_guid(iid));
824 *obj = NULL;
825 return E_NOINTERFACE;
828 IMarshal_AddRef(iface);
829 return S_OK;
832 static ULONG WINAPI marshal_AddRef(IMarshal *iface)
834 marshal *This = impl_from_IMarshal(iface);
835 TRACE("(%p)\n", This);
836 return InterlockedIncrement(&This->ref);
839 static ULONG WINAPI marshal_Release(IMarshal *iface)
841 marshal *This = impl_from_IMarshal(iface);
842 LONG ref;
844 TRACE("(%p)\n", This);
846 ref = InterlockedDecrement(&This->ref);
847 if(ref == 0)
849 HeapFree(GetProcessHeap(), 0, This);
852 return ref;
855 static HRESULT WINAPI marshal_GetUnmarshalClass(IMarshal *iface, REFIID iid, void *obj,
856 DWORD dwDestContext, void *pvDestContext,
857 DWORD mshlflags, CLSID *clsid)
859 marshal *This = impl_from_IMarshal(iface);
860 TRACE("(%p)->(%s, %p, %08x, %p, %08x, %p)\n", This, debugstr_guid(iid), obj, dwDestContext,
861 pvDestContext, mshlflags, clsid);
863 *clsid = This->unmarshal_class;
864 return S_OK;
867 static HRESULT WINAPI marshal_GetMarshalSizeMax(IMarshal *iface, REFIID iid, void *obj,
868 DWORD dwDestContext, void *pvDestContext,
869 DWORD mshlflags, DWORD *size)
871 marshal *This = impl_from_IMarshal(iface);
872 TRACE("(%p)->(%s, %p, %08x, %p, %08x, %p)\n", This, debugstr_guid(iid), obj, dwDestContext,
873 pvDestContext, mshlflags, size);
875 return CoGetMarshalSizeMax(size, &IID_IWineRowServer, This->outer, dwDestContext, pvDestContext,
876 mshlflags);
879 static HRESULT WINAPI marshal_MarshalInterface(IMarshal *iface, IStream *stream, REFIID iid,
880 void *obj, DWORD dwDestContext, void *pvDestContext,
881 DWORD mshlflags)
883 marshal *This = impl_from_IMarshal(iface);
884 TRACE("(%p)->(%p, %s, %p, %08x, %p, %08x)\n", This, stream, debugstr_guid(iid), obj, dwDestContext,
885 pvDestContext, mshlflags);
887 return CoMarshalInterface(stream, &IID_IWineRowServer, This->outer, dwDestContext, pvDestContext, mshlflags);
890 static HRESULT WINAPI marshal_UnmarshalInterface(IMarshal *iface, IStream *stream,
891 REFIID iid, void **obj)
893 marshal *This = impl_from_IMarshal(iface);
894 HRESULT hr;
895 IWineRowServer *server;
896 IUnknown *proxy;
898 TRACE("(%p)->(%p, %s, %p)\n", This, stream, debugstr_guid(iid), obj);
899 *obj = NULL;
901 hr = CoUnmarshalInterface(stream, &IID_IWineRowServer, (void**)&server);
902 if(SUCCEEDED(hr))
904 hr = create_proxy(server, &This->unmarshal_class, &proxy);
905 if(SUCCEEDED(hr))
907 hr = IUnknown_QueryInterface(proxy, iid, obj);
908 IUnknown_Release(proxy);
910 IWineRowServer_Release(server);
913 TRACE("returing %p\n", *obj);
914 return hr;
917 static HRESULT WINAPI marshal_ReleaseMarshalData(IMarshal *iface, IStream *stream)
919 marshal *This = impl_from_IMarshal(iface);
920 TRACE("(%p)->(%p)\n", This, stream);
921 return CoReleaseMarshalData(stream);
924 static HRESULT WINAPI marshal_DisconnectObject(IMarshal *iface, DWORD dwReserved)
926 marshal *This = impl_from_IMarshal(iface);
927 FIXME("(%p)->(%08x)\n", This, dwReserved);
929 return E_NOTIMPL;
932 static const IMarshalVtbl marshal_vtbl =
934 marshal_QueryInterface,
935 marshal_AddRef,
936 marshal_Release,
937 marshal_GetUnmarshalClass,
938 marshal_GetMarshalSizeMax,
939 marshal_MarshalInterface,
940 marshal_UnmarshalInterface,
941 marshal_ReleaseMarshalData,
942 marshal_DisconnectObject
945 static HRESULT create_marshal(IUnknown *outer, const CLSID *class, void **obj)
947 marshal *marshal;
949 TRACE("(%p, %p)\n", outer, obj);
950 *obj = NULL;
952 marshal = HeapAlloc(GetProcessHeap(), 0, sizeof(*marshal));
953 if(!marshal) return E_OUTOFMEMORY;
955 marshal->unmarshal_class = *class;
956 marshal->outer = outer; /* don't ref outer unk */
957 marshal->marshal_vtbl = &marshal_vtbl;
958 marshal->ref = 1;
960 *obj = &marshal->marshal_vtbl;
961 TRACE("returing %p\n", *obj);
962 return S_OK;
965 HRESULT create_row_marshal(IUnknown *outer, void **obj)
967 TRACE("(%p, %p)\n", outer, obj);
968 return create_marshal(outer, &CLSID_wine_row_proxy, obj);
971 HRESULT create_rowset_marshal(IUnknown *outer, void **obj)
973 TRACE("(%p, %p)\n", outer, obj);
974 return create_marshal(outer, &CLSID_wine_rowset_proxy, obj);