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
24 #define NONAMELESSUNION
25 #define NONAMELESSSTRUCT
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)
63 return sizeof(FILETIME);
71 FIXME("Unhandled type %04x\n", type);
78 const IWineRowServerVtbl *vtbl;
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);
99 if(IsEqualIID(riid, &IID_IUnknown) ||
100 IsEqualIID(riid, &IID_IWineRowServer))
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);
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);
128 TRACE("(%p)\n", This);
130 ref = InterlockedDecrement(&This->ref);
133 IMarshal_Release(This->marshal);
134 if(This->inner_unk) IUnknown_Release(This->inner_unk);
135 HeapFree(GetProcessHeap(), 0, This);
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;
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;
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);
167 DBCOLUMNACCESS *cols;
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);
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;
209 static HRESULT WINAPI server_GetSourceRowset(IWineRowServer* iface, REFIID riid, IUnknown **ppRowset,
212 server *This = impl_from_IWineRowServer(iface);
213 FIXME("(%p): stub\n", This);
217 static HRESULT WINAPI server_Open(IWineRowServer* iface, IUnknown *pUnkOuter, DBID *pColumnID,
218 REFGUID rguidColumnType, DWORD dwBindFlags, REFIID riid,
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);
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);
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);
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);
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);
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);
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;
278 hr = IRowset_GetNextRows(rowset, hReserved, lRowsOffset, cRows, pcRowObtained, prghRows);
279 IRowset_Release(rowset);
280 TRACE("returning %08x, got %d rows\n", hr, *pcRowObtained);
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);
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);
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);
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);
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);
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);
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);
349 static HRESULT WINAPI server_GetProperties(IWineRowServer* iface, ULONG cPropertyIDSets,
350 const DBPROPIDSET *rgPropertyIDSets, ULONG *pcPropertySets,
351 DBPROPSET **prgPropertySets)
353 server *This = impl_from_IWineRowServer(iface);
354 FIXME("(%p)->(%d, %p, %p, %p)\n", This, cPropertyIDSets, rgPropertyIDSets, pcPropertySets, prgPropertySets);
358 static HRESULT WINAPI server_GetReferencedRowset(IWineRowServer* iface, DBORDINAL iOrdinal,
359 REFIID riid, IUnknown **ppReferencedRowset)
361 server *This = impl_from_IWineRowServer(iface);
362 FIXME("(%p): stub\n", This);
366 static HRESULT WINAPI server_GetSpecification(IWineRowServer* iface, REFIID riid,
367 IUnknown **ppSpecification)
369 server *This = impl_from_IWineRowServer(iface);
370 FIXME("(%p): stub\n", This);
374 static HRESULT WINAPI server_AddRefAccessor(IWineRowServer* iface, HACCESSOR hAccessor,
375 DBREFCOUNT *pcRefCount)
377 server *This = impl_from_IWineRowServer(iface);
378 FIXME("(%p): stub\n", This);
382 static HRESULT WINAPI server_CreateAccessor(IWineRowServer* iface, DBACCESSORFLAGS dwAccessorFlags,
383 DBCOUNTITEM cBindings, const DBBINDING *rgBindings, DBLENGTH cbRowSize,
384 HACCESSOR *phAccessor, DBBINDSTATUS *rgStatus)
386 server *This = impl_from_IWineRowServer(iface);
387 FIXME("(%p)->(%08x, %d, %p, %d, %p, %p): stub\n", This, dwAccessorFlags, cBindings, rgBindings, cbRowSize, phAccessor, rgStatus);
391 static HRESULT WINAPI server_GetBindings(IWineRowServer* iface, HACCESSOR hAccessor,
392 DBACCESSORFLAGS *pdwAccessorFlags, DBCOUNTITEM *pcBindings,
393 DBBINDING **prgBindings)
395 server *This = impl_from_IWineRowServer(iface);
396 FIXME("(%p)->(%08lx, %p, %p, %p): stub\n", This, hAccessor, pdwAccessorFlags, pcBindings, prgBindings);
400 static HRESULT WINAPI server_ReleaseAccessor(IWineRowServer* iface, HACCESSOR hAccessor,
401 DBREFCOUNT *pcRefCount)
403 server *This = impl_from_IWineRowServer(iface);
404 FIXME("(%p)->(%08lx, %p): stub\n", This, hAccessor, pcRefCount);
408 static const IWineRowServerVtbl server_vtbl =
410 server_QueryInterface,
416 server_GetSourceRowset,
423 server_RestartPosition,
426 server_GetRowsByBookmark,
428 server_GetProperties,
429 server_GetReferencedRowset,
430 server_GetSpecification,
431 server_AddRefAccessor,
432 server_CreateAccessor,
434 server_ReleaseAccessor
437 static HRESULT create_server(IUnknown *outer, const CLSID *class, void **obj)
440 TRACE("(%p, %s, %p)\n", outer, debugstr_guid(class), obj);
444 server = HeapAlloc(GetProcessHeap(), 0, sizeof(*server));
445 if(!server) return E_OUTOFMEMORY;
447 server->vtbl = &server_vtbl;
449 server->class = *class;
450 server->inner_unk = NULL;
451 if(IsEqualGUID(class, &CLSID_wine_row_server))
452 create_row_marshal((IUnknown*)server, (void**)&server->marshal);
453 else if(IsEqualGUID(class, &CLSID_wine_rowset_server))
454 create_rowset_marshal((IUnknown*)server, (void**)&server->marshal);
456 ERR("create_server called with class %s\n", debugstr_guid(class));
462 HRESULT create_row_server(IUnknown *outer, void **obj)
464 return create_server(outer, &CLSID_wine_row_server, obj);
467 HRESULT create_rowset_server(IUnknown *outer, void **obj)
469 return create_server(outer, &CLSID_wine_rowset_server, obj);
474 const IRowVtbl *row_vtbl;
475 const IRowChangeVtbl *row_change_vtbl;
479 IWineRowServer *server;
482 static inline row_proxy *impl_from_IRow(IRow *iface)
484 return (row_proxy *)((char*)iface - FIELD_OFFSET(row_proxy, row_vtbl));
487 static inline row_proxy *impl_from_IRowChange(IRowChange *iface)
489 return (row_proxy *)((char*)iface - FIELD_OFFSET(row_proxy, row_change_vtbl));
492 static HRESULT WINAPI row_QueryInterface(IRow *iface, REFIID iid, void **obj)
494 row_proxy *This = impl_from_IRow(iface);
495 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(iid), obj);
497 if(IsEqualIID(iid, &IID_IUnknown) ||
498 IsEqualIID(iid, &IID_IRow))
500 *obj = &This->row_vtbl;
502 else if(IsEqualIID(iid, &IID_IRowChange))
504 *obj = &This->row_change_vtbl;
508 FIXME("interface %s not implemented\n", debugstr_guid(iid));
509 return E_NOINTERFACE;
516 static ULONG WINAPI row_AddRef(IRow *iface)
518 row_proxy *This = impl_from_IRow(iface);
519 TRACE("(%p)\n", This);
521 return InterlockedIncrement(&This->ref);
524 static ULONG WINAPI row_Release(IRow *iface)
526 row_proxy *This = impl_from_IRow(iface);
529 TRACE("(%p)\n", This);
531 ref = InterlockedDecrement(&This->ref);
534 if(This->server) IWineRowServer_Release(This->server);
535 HeapFree(GetProcessHeap(), 0, This);
541 static HRESULT WINAPI row_GetColumns(IRow* iface, DBORDINAL cColumns, DBCOLUMNACCESS rgColumns[])
543 row_proxy *This = impl_from_IRow(iface);
545 wine_getcolumns_in *in_data;
546 wine_getcolumns_out *out_data;
549 TRACE("(%p)->(%d, %p)\n", This, cColumns, rgColumns);
551 in_data = CoTaskMemAlloc(cColumns * sizeof(in_data[0]));
552 out_data = CoTaskMemAlloc(cColumns * sizeof(out_data[0]));
554 for(i = 0; i < cColumns; i++)
556 TRACE("%d:\tdata %p data_len %d status %08x max_len %d type %04x\n", i, rgColumns[i].pData,
557 rgColumns[i].cbDataLen, rgColumns[i].dwStatus, rgColumns[i].cbMaxLen, rgColumns[i].wType);
558 in_data[i].columnid = rgColumns[i].columnid;
559 in_data[i].max_len = rgColumns[i].cbMaxLen;
560 in_data[i].type = rgColumns[i].wType;
561 in_data[i].precision = rgColumns[i].bPrecision;
562 in_data[i].scale = rgColumns[i].bScale;
565 hr = IWineRowServer_GetColumns(This->server, cColumns, in_data, out_data);
567 for(i = 0; i < cColumns; i++)
569 rgColumns[i].cbDataLen = out_data[i].data_len;
570 rgColumns[i].dwStatus = out_data[i].status;
571 if(rgColumns[i].dwStatus == DBSTATUS_S_OK)
572 memcpy(rgColumns[i].pData, &V_I1(&out_data[i].v), out_data[i].data_len);
575 CoTaskMemFree(out_data);
576 CoTaskMemFree(in_data);
580 static HRESULT WINAPI row_GetSourceRowset(IRow* iface, REFIID riid, IUnknown **ppRowset,
583 row_proxy *This = impl_from_IRow(iface);
585 FIXME("(%p)->(%s, %p, %p): stub\n", This, debugstr_guid(riid), ppRowset, phRow);
590 static HRESULT WINAPI row_Open(IRow* iface, IUnknown *pUnkOuter,
591 DBID *pColumnID, REFGUID rguidColumnType,
592 DWORD dwBindFlags, REFIID riid, IUnknown **ppUnk)
594 row_proxy *This = impl_from_IRow(iface);
596 FIXME("(%p)->(%p, %p, %s, %08x, %s, %p): stub\n", This, pUnkOuter, pColumnID, debugstr_guid(rguidColumnType),
597 dwBindFlags, debugstr_guid(riid), ppUnk);
602 static const IRowVtbl row_vtbl =
612 static HRESULT WINAPI row_change_QueryInterface(IRowChange *iface, REFIID iid, void **obj)
614 row_proxy *This = impl_from_IRowChange(iface);
615 return IUnknown_QueryInterface((IUnknown *)This, iid, obj);
618 static ULONG WINAPI row_change_AddRef(IRowChange *iface)
620 row_proxy *This = impl_from_IRowChange(iface);
621 return IUnknown_AddRef((IUnknown*)This);
624 static ULONG WINAPI row_change_Release(IRowChange *iface)
626 row_proxy *This = impl_from_IRowChange(iface);
627 return IUnknown_Release((IUnknown*)This);
630 static HRESULT WINAPI row_change_SetColumns(IRowChange *iface, DBORDINAL cColumns,
631 DBCOLUMNACCESS rgColumns[])
633 row_proxy *This = impl_from_IRowChange(iface);
634 FIXME("(%p)->(%d, %p)\n", This, cColumns, rgColumns);
638 static const IRowChangeVtbl row_change_vtbl =
640 row_change_QueryInterface,
643 row_change_SetColumns
646 static HRESULT create_row_proxy(IWineRowServer *server, IUnknown **obj)
650 TRACE("(%p, %p)\n", server, obj);
653 proxy = HeapAlloc(GetProcessHeap(), 0, sizeof(*proxy));
654 if(!proxy) return E_OUTOFMEMORY;
656 proxy->row_vtbl = &row_vtbl;
657 proxy->row_change_vtbl = &row_change_vtbl;
659 IWineRowServer_AddRef(server);
660 proxy->server = server;
662 *obj = (IUnknown*)&proxy->row_vtbl;
663 TRACE("returing %p\n", *obj);
669 const IRowsetVtbl *rowset_vtbl;
673 IWineRowServer *server;
676 static inline rowset_proxy *impl_from_IRowset(IRowset *iface)
678 return (rowset_proxy *)((char*)iface - FIELD_OFFSET(rowset_proxy, rowset_vtbl));
681 static HRESULT WINAPI rowset_QueryInterface(IRowset *iface, REFIID iid, void **obj)
683 rowset_proxy *This = impl_from_IRowset(iface);
684 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(iid), obj);
688 if(IsEqualIID(iid, &IID_IUnknown) ||
689 IsEqualIID(iid, &IID_IRowset))
691 *obj = &This->rowset_vtbl;
695 FIXME("interface %s not implemented\n", debugstr_guid(iid));
696 return E_NOINTERFACE;
699 IRowset_AddRef(iface);
703 static ULONG WINAPI rowset_AddRef(IRowset *iface)
705 rowset_proxy *This = impl_from_IRowset(iface);
706 TRACE("(%p)\n", This);
708 return InterlockedIncrement(&This->ref);
711 static ULONG WINAPI rowset_Release(IRowset *iface)
713 rowset_proxy *This = impl_from_IRowset(iface);
716 TRACE("(%p)\n", This);
718 ref = InterlockedDecrement(&This->ref);
721 if(This->server) IWineRowServer_Release(This->server);
722 HeapFree(GetProcessHeap(), 0, This);
728 static HRESULT WINAPI rowset_AddRefRows(IRowset *iface, DBCOUNTITEM cRows, const HROW rghRows[],
729 DBREFCOUNT rgRefCounts[], DBROWSTATUS rgRowStatus[])
731 rowset_proxy *This = impl_from_IRowset(iface);
733 DBREFCOUNT *refs = rgRefCounts;
734 DBSTATUS *stats = rgRowStatus;
736 TRACE("(%p)->(%d, %p, %p, %p)\n", This, cRows, rghRows, rgRefCounts, rgRowStatus);
738 if(!refs) refs = CoTaskMemAlloc(cRows * sizeof(refs[0]));
739 if(!stats) stats = CoTaskMemAlloc(cRows * sizeof(stats[0]));
741 hr = IWineRowServer_AddRefRows(This->server, cRows, rghRows, refs, stats);
743 if(refs != rgRefCounts) CoTaskMemFree(refs);
744 if(stats != rgRowStatus) CoTaskMemFree(stats);
749 static HRESULT WINAPI rowset_GetData(IRowset *iface, HROW hRow, HACCESSOR hAccessor, void *pData)
751 rowset_proxy *This = impl_from_IRowset(iface);
753 FIXME("(%p)->(%lx, %lx, %p): stub\n", This, hRow, hAccessor, pData);
758 static HRESULT WINAPI rowset_GetNextRows(IRowset *iface, HCHAPTER hReserved, DBROWOFFSET lRowsOffset,
759 DBROWCOUNT cRows, DBCOUNTITEM *pcRowObtained, HROW **prghRows)
761 rowset_proxy *This = impl_from_IRowset(iface);
765 TRACE("(%p)->(%08lx, %d, %d, %p, %p)\n", This, hReserved, lRowsOffset, cRows, pcRowObtained, prghRows);
767 hr = IWineRowServer_GetNextRows(This->server, hReserved, lRowsOffset, cRows, pcRowObtained, &rows);
770 memcpy(*prghRows, rows, *pcRowObtained * sizeof(rows[0]));
779 static HRESULT WINAPI rowset_ReleaseRows(IRowset *iface, DBCOUNTITEM cRows, const HROW rghRows[],
780 DBROWOPTIONS rgRowOptions[], DBREFCOUNT rgRefCounts[], DBROWSTATUS rgRowStatus[])
782 rowset_proxy *This = impl_from_IRowset(iface);
784 DBROWOPTIONS *options = rgRowOptions;
785 DBREFCOUNT *refs = rgRefCounts;
786 DBROWSTATUS *status = rgRowStatus;
788 TRACE("(%p)->(%d, %p, %p, %p, %p)\n", This, cRows, rghRows, rgRowOptions, rgRefCounts, rgRowStatus);
792 options = CoTaskMemAlloc(cRows * sizeof(options[0]));
793 memset(options, 0, cRows * sizeof(options[0]));
795 if(!refs) refs = CoTaskMemAlloc(cRows * sizeof(refs[0]));
796 if(!status) status = CoTaskMemAlloc(cRows * sizeof(status[0]));
798 hr = IWineRowServer_ReleaseRows(This->server, cRows, rghRows, options, refs, status);
800 if(status != rgRowStatus) CoTaskMemFree(status);
801 if(refs != rgRefCounts) CoTaskMemFree(refs);
802 if(options != rgRowOptions) CoTaskMemFree(options);
807 static HRESULT WINAPI rowset_RestartPosition(IRowset* iface, HCHAPTER hReserved)
809 rowset_proxy *This = impl_from_IRowset(iface);
811 FIXME("(%p)->(%lx): stub\n", This, hReserved);
816 static const IRowsetVtbl rowset_vtbl =
818 rowset_QueryInterface,
825 rowset_RestartPosition
828 HRESULT create_rowset_proxy(IWineRowServer *server, IUnknown **obj)
832 TRACE("(%p, %p)\n", server, obj);
835 proxy = HeapAlloc(GetProcessHeap(), 0, sizeof(*proxy));
836 if(!proxy) return E_OUTOFMEMORY;
838 proxy->rowset_vtbl = &rowset_vtbl;
840 IWineRowServer_AddRef(server);
841 proxy->server = server;
843 *obj = (IUnknown *)&proxy->rowset_vtbl;
844 TRACE("returing %p\n", *obj);
848 static HRESULT create_proxy(IWineRowServer *server, const CLSID *class, IUnknown **obj)
852 if(IsEqualGUID(class, &CLSID_wine_row_proxy))
853 return create_row_proxy(server, obj);
854 else if(IsEqualGUID(class, &CLSID_wine_rowset_proxy))
855 return create_rowset_proxy(server, obj);
857 FIXME("Unhandled proxy class %s\n", debugstr_guid(class));
865 const IMarshalVtbl *marshal_vtbl;
868 CLSID unmarshal_class;
872 static inline marshal *impl_from_IMarshal(IMarshal *iface)
874 return (marshal *)((char*)iface - FIELD_OFFSET(marshal, marshal_vtbl));
877 static HRESULT WINAPI marshal_QueryInterface(IMarshal *iface, REFIID iid, void **obj)
879 marshal *This = impl_from_IMarshal(iface);
880 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(iid), obj);
882 if(IsEqualIID(iid, &IID_IUnknown) ||
883 IsEqualIID(iid, &IID_IMarshal))
889 FIXME("interface %s not implemented\n", debugstr_guid(iid));
891 return E_NOINTERFACE;
894 IMarshal_AddRef(iface);
898 static ULONG WINAPI marshal_AddRef(IMarshal *iface)
900 marshal *This = impl_from_IMarshal(iface);
901 TRACE("(%p)\n", This);
902 return InterlockedIncrement(&This->ref);
905 static ULONG WINAPI marshal_Release(IMarshal *iface)
907 marshal *This = impl_from_IMarshal(iface);
910 TRACE("(%p)\n", This);
912 ref = InterlockedDecrement(&This->ref);
915 HeapFree(GetProcessHeap(), 0, This);
921 static HRESULT WINAPI marshal_GetUnmarshalClass(IMarshal *iface, REFIID iid, void *obj,
922 DWORD dwDestContext, void *pvDestContext,
923 DWORD mshlflags, CLSID *clsid)
925 marshal *This = impl_from_IMarshal(iface);
926 TRACE("(%p)->(%s, %p, %08x, %p, %08x, %p)\n", This, debugstr_guid(iid), obj, dwDestContext,
927 pvDestContext, mshlflags, clsid);
929 *clsid = This->unmarshal_class;
933 static HRESULT WINAPI marshal_GetMarshalSizeMax(IMarshal *iface, REFIID iid, void *obj,
934 DWORD dwDestContext, void *pvDestContext,
935 DWORD mshlflags, DWORD *size)
937 marshal *This = impl_from_IMarshal(iface);
938 TRACE("(%p)->(%s, %p, %08x, %p, %08x, %p)\n", This, debugstr_guid(iid), obj, dwDestContext,
939 pvDestContext, mshlflags, size);
941 return CoGetMarshalSizeMax(size, &IID_IWineRowServer, This->outer, dwDestContext, pvDestContext,
945 static HRESULT WINAPI marshal_MarshalInterface(IMarshal *iface, IStream *stream, REFIID iid,
946 void *obj, DWORD dwDestContext, void *pvDestContext,
949 marshal *This = impl_from_IMarshal(iface);
950 TRACE("(%p)->(%p, %s, %p, %08x, %p, %08x)\n", This, stream, debugstr_guid(iid), obj, dwDestContext,
951 pvDestContext, mshlflags);
953 return CoMarshalInterface(stream, &IID_IWineRowServer, This->outer, dwDestContext, pvDestContext, mshlflags);
956 static HRESULT WINAPI marshal_UnmarshalInterface(IMarshal *iface, IStream *stream,
957 REFIID iid, void **obj)
959 marshal *This = impl_from_IMarshal(iface);
961 IWineRowServer *server;
964 TRACE("(%p)->(%p, %s, %p)\n", This, stream, debugstr_guid(iid), obj);
967 hr = CoUnmarshalInterface(stream, &IID_IWineRowServer, (void**)&server);
970 hr = create_proxy(server, &This->unmarshal_class, &proxy);
973 hr = IUnknown_QueryInterface(proxy, iid, obj);
974 IUnknown_Release(proxy);
976 IWineRowServer_Release(server);
979 TRACE("returing %p\n", *obj);
983 static HRESULT WINAPI marshal_ReleaseMarshalData(IMarshal *iface, IStream *stream)
985 marshal *This = impl_from_IMarshal(iface);
986 TRACE("(%p)->(%p)\n", This, stream);
987 return CoReleaseMarshalData(stream);
990 static HRESULT WINAPI marshal_DisconnectObject(IMarshal *iface, DWORD dwReserved)
992 marshal *This = impl_from_IMarshal(iface);
993 FIXME("(%p)->(%08x)\n", This, dwReserved);
998 static const IMarshalVtbl marshal_vtbl =
1000 marshal_QueryInterface,
1003 marshal_GetUnmarshalClass,
1004 marshal_GetMarshalSizeMax,
1005 marshal_MarshalInterface,
1006 marshal_UnmarshalInterface,
1007 marshal_ReleaseMarshalData,
1008 marshal_DisconnectObject
1011 static HRESULT create_marshal(IUnknown *outer, const CLSID *class, void **obj)
1015 TRACE("(%p, %p)\n", outer, obj);
1018 marshal = HeapAlloc(GetProcessHeap(), 0, sizeof(*marshal));
1019 if(!marshal) return E_OUTOFMEMORY;
1021 marshal->unmarshal_class = *class;
1022 marshal->outer = outer; /* don't ref outer unk */
1023 marshal->marshal_vtbl = &marshal_vtbl;
1026 *obj = &marshal->marshal_vtbl;
1027 TRACE("returing %p\n", *obj);
1031 HRESULT create_row_marshal(IUnknown *outer, void **obj)
1033 TRACE("(%p, %p)\n", outer, obj);
1034 return create_marshal(outer, &CLSID_wine_row_proxy, obj);
1037 HRESULT create_rowset_marshal(IUnknown *outer, void **obj)
1039 TRACE("(%p, %p)\n", outer, obj);
1040 return create_marshal(outer, &CLSID_wine_rowset_proxy, obj);