ntdll: Use an __ms_va_list in sscanf (Clang).
[wine/multimedia.git] / dlls / msdaps / row_server.c
blob784ade8418d7540f5c46aa6edd881c3284c7dfc4
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
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "winuser.h"
29 #include "winerror.h"
30 #include "objbase.h"
31 #include "oleauto.h"
32 #include "oledb.h"
34 #include "row_server.h"
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(oledb);
40 static inline DBLENGTH db_type_size(DBTYPE type, DBLENGTH var_len)
42 switch(type)
44 case DBTYPE_I1:
45 case DBTYPE_UI1:
46 return 1;
47 case DBTYPE_I2:
48 case DBTYPE_UI2:
49 return 2;
50 case DBTYPE_I4:
51 case DBTYPE_UI4:
52 case DBTYPE_R4:
53 return 4;
54 case DBTYPE_I8:
55 case DBTYPE_UI8:
56 case DBTYPE_R8:
57 return 8;
58 case DBTYPE_CY:
59 return sizeof(CY);
60 case DBTYPE_FILETIME:
61 return sizeof(FILETIME);
62 case DBTYPE_BSTR:
63 return sizeof(BSTR);
64 case DBTYPE_GUID:
65 return sizeof(GUID);
66 case DBTYPE_WSTR:
67 return var_len;
68 default:
69 FIXME("Unhandled type %04x\n", type);
70 return 0;
74 typedef struct
76 IWineRowServer IWineRowServer_iface;
78 LONG ref;
80 CLSID class;
81 IMarshal *marshal;
82 IUnknown *inner_unk;
83 } server;
85 static inline server *impl_from_IWineRowServer(IWineRowServer *iface)
87 return CONTAINING_RECORD(iface, server, IWineRowServer_iface);
90 static HRESULT WINAPI server_QueryInterface(IWineRowServer *iface, REFIID riid, void **obj)
92 server *This = impl_from_IWineRowServer(iface);
93 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), obj);
95 *obj = NULL;
97 if(IsEqualIID(riid, &IID_IUnknown) ||
98 IsEqualIID(riid, &IID_IWineRowServer))
100 *obj = iface;
102 else
104 if(!IsEqualIID(riid, &IID_IMarshal)) /* We use standard marshalling */
105 FIXME("interface %s not implemented\n", debugstr_guid(riid));
106 return E_NOINTERFACE;
109 IWineRowServer_AddRef(iface);
110 return S_OK;
113 static ULONG WINAPI server_AddRef(IWineRowServer *iface)
115 server *This = impl_from_IWineRowServer(iface);
116 TRACE("(%p)\n", This);
118 return InterlockedIncrement(&This->ref);
121 static ULONG WINAPI server_Release(IWineRowServer *iface)
123 server *This = impl_from_IWineRowServer(iface);
124 LONG ref;
126 TRACE("(%p)\n", This);
128 ref = InterlockedDecrement(&This->ref);
129 if(ref == 0)
131 IMarshal_Release(This->marshal);
132 if(This->inner_unk) IUnknown_Release(This->inner_unk);
133 HeapFree(GetProcessHeap(), 0, This);
136 return ref;
139 static HRESULT WINAPI server_SetInnerUnk(IWineRowServer *iface, IUnknown *inner)
141 server *This = impl_from_IWineRowServer(iface);
143 if(This->inner_unk) IUnknown_Release(This->inner_unk);
145 if(inner) IUnknown_AddRef(inner);
146 This->inner_unk = inner;
147 return S_OK;
150 static HRESULT WINAPI server_GetMarshal(IWineRowServer *iface, IMarshal **marshal)
152 server *This = impl_from_IWineRowServer(iface);
154 IMarshal_AddRef(This->marshal);
155 *marshal = This->marshal;
156 return S_OK;
159 static HRESULT WINAPI server_GetColumns(IWineRowServer* iface, DBORDINAL num_cols,
160 wine_getcolumns_in *in_data, wine_getcolumns_out *out_data)
162 server *This = impl_from_IWineRowServer(iface);
163 HRESULT hr;
164 DBORDINAL i;
165 DBCOLUMNACCESS *cols;
166 IRow *row;
168 TRACE("(%p)->(%ld, %p, %p)\n", This, num_cols, in_data, out_data);
170 hr = IUnknown_QueryInterface(This->inner_unk, &IID_IRow, (void**)&row);
171 if(FAILED(hr)) return hr;
173 cols = CoTaskMemAlloc(num_cols * sizeof(cols[0]));
175 for(i = 0; i < num_cols; i++)
177 TRACE("%ld:\tmax_len %ld type %04x\n", i, in_data[i].max_len, in_data[i].type);
178 cols[i].pData = CoTaskMemAlloc(db_type_size(in_data[i].type, in_data[i].max_len));
179 cols[i].columnid = in_data[i].columnid;
180 cols[i].cbMaxLen = in_data[i].max_len;
181 cols[i].wType = in_data[i].type;
182 cols[i].bPrecision = in_data[i].precision;
183 cols[i].bScale = in_data[i].scale;
186 hr = IRow_GetColumns(row, num_cols, cols);
187 IRow_Release(row);
189 for(i = 0; i < num_cols; i++)
191 VariantInit(&out_data[i].v);
192 if(cols[i].dwStatus == DBSTATUS_S_OK)
194 V_VT(&out_data[i].v) = in_data[i].type;
195 memcpy(&V_I1(&out_data[i].v), cols[i].pData, cols[i].cbDataLen);
197 CoTaskMemFree(cols[i].pData);
198 out_data[i].data_len = cols[i].cbDataLen;
199 out_data[i].status = cols[i].dwStatus;
202 CoTaskMemFree(cols);
204 return hr;
207 static HRESULT WINAPI server_GetSourceRowset(IWineRowServer* iface, REFIID riid, IUnknown **ppRowset,
208 HROW *phRow)
210 server *This = impl_from_IWineRowServer(iface);
211 FIXME("(%p): stub\n", This);
212 return E_NOTIMPL;
215 static HRESULT WINAPI server_Open(IWineRowServer* iface, IUnknown *pUnkOuter, DBID *pColumnID,
216 REFGUID rguidColumnType, DWORD dwBindFlags, REFIID riid,
217 IUnknown **ppUnk)
219 server *This = impl_from_IWineRowServer(iface);
220 IRow *row;
221 HRESULT hr;
222 IWineRowServer *new_server;
223 IMarshal *marshal;
224 IUnknown *obj;
226 TRACE("(%p)->(%p, %p, %s, %08x, %s, %p)\n", This, pUnkOuter, pColumnID, debugstr_guid(rguidColumnType),
227 dwBindFlags, debugstr_guid(riid), ppUnk);
229 *ppUnk = NULL;
231 hr = IUnknown_QueryInterface(This->inner_unk, &IID_IRow, (void**)&row);
232 if(FAILED(hr)) return hr;
234 if(IsEqualGUID(rguidColumnType, &DBGUID_ROWSET))
235 hr = CoCreateInstance(&CLSID_wine_rowset_server, NULL, CLSCTX_INPROC_SERVER, &IID_IWineRowServer, (void**)&new_server);
236 else
238 FIXME("Unhandled object %s\n", debugstr_guid(rguidColumnType));
239 hr = E_NOTIMPL;
242 if(FAILED(hr))
244 IRow_Release(row);
245 return hr;
248 IWineRowServer_GetMarshal(new_server, &marshal);
249 hr = IRow_Open(row, (IUnknown*)marshal, pColumnID, rguidColumnType, dwBindFlags, &IID_IUnknown, &obj);
250 IMarshal_Release(marshal);
251 IRow_Release(row);
253 if(FAILED(hr))
255 IWineRowServer_Release(new_server);
256 return hr;
259 IWineRowServer_SetInnerUnk(new_server, obj);
260 hr = IUnknown_QueryInterface(obj, riid, (void**)ppUnk);
261 IUnknown_Release(obj);
263 TRACE("returning %08x\n", hr);
264 return hr;
267 static HRESULT WINAPI server_SetColumns(IWineRowServer* iface, DBORDINAL num_cols,
268 wine_setcolumns_in *in_data, DBSTATUS *status)
270 server *This = impl_from_IWineRowServer(iface);
271 HRESULT hr;
272 DBORDINAL i;
273 DBCOLUMNACCESS *cols;
274 IRowChange *row_change;
276 TRACE("(%p)->(%ld, %p, %p)\n", This, num_cols, in_data, status);
277 hr = IUnknown_QueryInterface(This->inner_unk, &IID_IRowChange, (void**)&row_change);
278 if(FAILED(hr)) return hr;
280 cols = CoTaskMemAlloc(num_cols * sizeof(cols[0]));
282 for(i = 0; i < num_cols; i++)
284 TRACE("%ld:\ttype %04x\n", i, in_data[i].type);
285 cols[i].pData = CoTaskMemAlloc(db_type_size(in_data[i].type, in_data[i].max_len));
286 memcpy(cols[i].pData, &V_I1(&in_data[i].v), db_type_size(in_data[i].type, in_data[i].max_len));
287 cols[i].columnid = in_data[i].columnid;
288 cols[i].cbDataLen = in_data[i].data_len;
289 cols[i].dwStatus = in_data[i].status;
290 cols[i].cbMaxLen = in_data[i].max_len;
291 cols[i].wType = in_data[i].type;
292 cols[i].bPrecision = in_data[i].precision;
293 cols[i].bScale = in_data[i].scale;
296 hr = IRowChange_SetColumns(row_change, num_cols, cols);
297 IRowChange_Release(row_change);
299 for(i = 0; i < num_cols; i++)
301 CoTaskMemFree(cols[i].pData);
302 status[i] = cols[i].dwStatus;
305 CoTaskMemFree(cols);
307 return hr;
310 static HRESULT WINAPI server_AddRefRows(IWineRowServer* iface, DBCOUNTITEM cRows,
311 const HROW rghRows[], DBREFCOUNT rgRefCounts[],
312 DBROWSTATUS rgRowStatus[])
314 server *This = impl_from_IWineRowServer(iface);
315 IRowset *rowset;
316 HRESULT hr;
318 TRACE("(%p)->(%ld, %p, %p, %p)\n", This, cRows, rghRows, rgRefCounts, rgRowStatus);
320 hr = IUnknown_QueryInterface(This->inner_unk, &IID_IRowset, (void**)&rowset);
321 if(FAILED(hr)) return hr;
323 hr = IRowset_AddRefRows(rowset, cRows, rghRows, rgRefCounts, rgRowStatus);
325 IRowset_Release(rowset);
326 TRACE("returning %08x\n", hr);
327 return hr;
330 static HRESULT WINAPI server_GetData(IWineRowServer* iface, HROW hRow,
331 HACCESSOR hAccessor, BYTE *pData, DWORD size)
333 server *This = impl_from_IWineRowServer(iface);
334 IRowset *rowset;
335 HRESULT hr;
337 TRACE("(%p)->(%08lx, %08lx, %p, %d)\n", This, hRow, hAccessor, pData, size);
339 hr = IUnknown_QueryInterface(This->inner_unk, &IID_IRowset, (void**)&rowset);
340 if(FAILED(hr)) return hr;
342 hr = IRowset_GetData(rowset, hRow, hAccessor, pData);
344 IRowset_Release(rowset);
345 TRACE("returning %08x\n", hr);
346 return hr;
349 static HRESULT WINAPI server_GetNextRows(IWineRowServer* iface, HCHAPTER hReserved, DBROWOFFSET lRowsOffset,
350 DBROWCOUNT cRows, DBCOUNTITEM *pcRowObtained, HROW **prghRows)
352 server *This = impl_from_IWineRowServer(iface);
353 IRowset *rowset;
354 HRESULT hr;
356 TRACE("(%p)->(%08lx, %ld, %ld, %p, %p)\n", This, hReserved, lRowsOffset, cRows, pcRowObtained, prghRows);
358 hr = IUnknown_QueryInterface(This->inner_unk, &IID_IRowset, (void**)&rowset);
359 if(FAILED(hr)) return hr;
361 *prghRows = NULL;
363 hr = IRowset_GetNextRows(rowset, hReserved, lRowsOffset, cRows, pcRowObtained, prghRows);
364 IRowset_Release(rowset);
365 TRACE("returning %08x, got %ld rows\n", hr, *pcRowObtained);
366 return hr;
369 static HRESULT WINAPI server_ReleaseRows(IWineRowServer* iface, DBCOUNTITEM cRows, const HROW rghRows[],
370 DBROWOPTIONS rgRowOptions[], DBREFCOUNT rgRefCounts[], DBROWSTATUS rgRowStatus[])
372 server *This = impl_from_IWineRowServer(iface);
373 IRowset *rowset;
374 HRESULT hr;
376 TRACE("(%p)->(%ld, %p, %p, %p, %p)\n", This, cRows, rghRows, rgRowOptions, rgRefCounts, rgRowStatus);
378 hr = IUnknown_QueryInterface(This->inner_unk, &IID_IRowset, (void**)&rowset);
379 if(FAILED(hr)) return hr;
381 hr = IRowset_ReleaseRows(rowset, cRows, rghRows, rgRowOptions, rgRefCounts, rgRowStatus);
382 IRowset_Release(rowset);
384 TRACE("returning %08x\n", hr);
385 return hr;
388 static HRESULT WINAPI server_RestartPosition(IWineRowServer* iface, HCHAPTER hReserved)
390 server *This = impl_from_IWineRowServer(iface);
391 FIXME("(%p)->(%08lx): stub\n", This, hReserved);
392 return E_NOTIMPL;
395 static HRESULT WINAPI server_Compare(IWineRowServer *iface, HCHAPTER hReserved, DBBKMARK cbBookmark1,
396 const BYTE *pBookmark1, DBBKMARK cbBookmark2, const BYTE *pBookmark2,
397 DBCOMPARE *pComparison)
399 server *This = impl_from_IWineRowServer(iface);
400 FIXME("(%p): stub\n", This);
401 return E_NOTIMPL;
404 static HRESULT WINAPI server_GetRowsAt(IWineRowServer *iface, HWATCHREGION hReserved1, HCHAPTER hReserved2,
405 DBBKMARK cbBookmark, const BYTE *pBookmark, DBROWOFFSET lRowsOffset,
406 DBROWCOUNT cRows, DBCOUNTITEM *pcRowsObtained, HROW **prghRows)
408 server *This = impl_from_IWineRowServer(iface);
409 IRowsetLocate *rowsetlocate;
410 HRESULT hr;
412 TRACE("(%p)->(%08lx, %08lx, %ld, %p, %ld, %ld, %p, %p\n", This, hReserved1, hReserved2, cbBookmark, pBookmark, lRowsOffset, cRows,
413 pcRowsObtained, prghRows);
415 *prghRows = NULL;
417 hr = IUnknown_QueryInterface(This->inner_unk, &IID_IRowsetLocate, (void**)&rowsetlocate);
418 if(FAILED(hr)) return hr;
420 hr = IRowsetLocate_GetRowsAt(rowsetlocate, hReserved1, hReserved2, cbBookmark, pBookmark, lRowsOffset,
421 cRows, pcRowsObtained, prghRows);
422 IRowsetLocate_Release(rowsetlocate);
424 TRACE("returning %08x\n", hr);
425 return hr;
428 static HRESULT WINAPI server_GetRowsByBookmark(IWineRowServer *iface, HCHAPTER hReserved, DBCOUNTITEM cRows,
429 const DBBKMARK rgcbBookmarks[], const BYTE * rgpBookmarks[],
430 HROW rghRows[], DBROWSTATUS rgRowStatus[])
432 server *This = impl_from_IWineRowServer(iface);
433 FIXME("(%p): stub\n", This);
434 return E_NOTIMPL;
437 static HRESULT WINAPI server_Hash(IWineRowServer *iface, HCHAPTER hReserved, DBBKMARK cBookmarks,
438 const DBBKMARK rgcbBookmarks[], const BYTE * rgpBookmarks[],
439 DBHASHVALUE rgHashedValues[], DBROWSTATUS rgBookmarkStatus[])
441 server *This = impl_from_IWineRowServer(iface);
442 FIXME("(%p): stub\n", This);
443 return E_NOTIMPL;
446 static HRESULT WINAPI server_GetProperties(IWineRowServer* iface, ULONG cPropertyIDSets,
447 const DBPROPIDSET *rgPropertyIDSets, ULONG *pcPropertySets,
448 DBPROPSET **prgPropertySets)
450 server *This = impl_from_IWineRowServer(iface);
451 IRowsetInfo *rowsetinfo;
452 HRESULT hr;
454 TRACE("(%p)->(%d, %p, %p, %p)\n", This, cPropertyIDSets, rgPropertyIDSets, pcPropertySets, prgPropertySets);
456 hr = IUnknown_QueryInterface(This->inner_unk, &IID_IRowsetInfo, (void**)&rowsetinfo);
457 if(FAILED(hr)) return hr;
459 hr = IRowsetInfo_GetProperties(rowsetinfo, cPropertyIDSets, rgPropertyIDSets, pcPropertySets, prgPropertySets);
460 IRowsetInfo_Release(rowsetinfo);
462 TRACE("returning %08x\n", hr);
463 return hr;
466 static HRESULT WINAPI server_GetReferencedRowset(IWineRowServer* iface, DBORDINAL iOrdinal,
467 REFIID riid, IUnknown **ppReferencedRowset)
469 server *This = impl_from_IWineRowServer(iface);
470 FIXME("(%p): stub\n", This);
471 return E_NOTIMPL;
474 static HRESULT WINAPI server_GetSpecification(IWineRowServer* iface, REFIID riid,
475 IUnknown **ppSpecification)
477 server *This = impl_from_IWineRowServer(iface);
478 FIXME("(%p): stub\n", This);
479 return E_NOTIMPL;
482 static HRESULT WINAPI server_AddRefAccessor(IWineRowServer* iface, HACCESSOR hAccessor,
483 DBREFCOUNT *pcRefCount)
485 server *This = impl_from_IWineRowServer(iface);
486 FIXME("(%p): stub\n", This);
487 return E_NOTIMPL;
490 static HRESULT WINAPI server_CreateAccessor(IWineRowServer* iface, DBACCESSORFLAGS dwAccessorFlags,
491 DBCOUNTITEM cBindings, const DBBINDING *rgBindings, DBLENGTH cbRowSize,
492 HACCESSOR *phAccessor, DBBINDSTATUS *rgStatus)
494 server *This = impl_from_IWineRowServer(iface);
495 HRESULT hr;
496 IAccessor *accessor;
498 TRACE("(%p)->(%08x, %ld, %p, %ld, %p, %p)\n", This, dwAccessorFlags, cBindings, rgBindings, cbRowSize, phAccessor, rgStatus);
500 hr = IUnknown_QueryInterface(This->inner_unk, &IID_IAccessor, (void**)&accessor);
501 if(FAILED(hr)) return hr;
503 hr = IAccessor_CreateAccessor(accessor, dwAccessorFlags, cBindings, rgBindings, cbRowSize, phAccessor, rgStatus);
504 IAccessor_Release(accessor);
506 TRACE("returning %08x, accessor %08lx\n", hr, *phAccessor);
507 return hr;
510 static HRESULT WINAPI server_GetBindings(IWineRowServer* iface, HACCESSOR hAccessor,
511 DBACCESSORFLAGS *pdwAccessorFlags, DBCOUNTITEM *pcBindings,
512 DBBINDING **prgBindings)
514 server *This = impl_from_IWineRowServer(iface);
515 HRESULT hr;
516 IAccessor *accessor;
518 TRACE("(%p)->(%08lx, %p, %p, %p)\n", This, hAccessor, pdwAccessorFlags, pcBindings, prgBindings);
520 hr = IUnknown_QueryInterface(This->inner_unk, &IID_IAccessor, (void**)&accessor);
521 if(FAILED(hr)) return hr;
523 hr = IAccessor_GetBindings(accessor, hAccessor, pdwAccessorFlags, pcBindings, prgBindings);
524 IAccessor_Release(accessor);
526 TRACE("returning %08x\n", hr);
527 return hr;
530 static HRESULT WINAPI server_ReleaseAccessor(IWineRowServer* iface, HACCESSOR hAccessor,
531 DBREFCOUNT *pcRefCount)
533 server *This = impl_from_IWineRowServer(iface);
534 HRESULT hr;
535 IAccessor *accessor;
537 TRACE("(%p)->(%08lx, %p)\n", This, hAccessor, pcRefCount);
539 hr = IUnknown_QueryInterface(This->inner_unk, &IID_IAccessor, (void**)&accessor);
540 if(FAILED(hr)) return hr;
542 hr = IAccessor_ReleaseAccessor(accessor, hAccessor, pcRefCount);
543 IAccessor_Release(accessor);
545 return hr;
548 static const IWineRowServerVtbl server_vtbl =
550 server_QueryInterface,
551 server_AddRef,
552 server_Release,
553 server_SetInnerUnk,
554 server_GetMarshal,
555 server_GetColumns,
556 server_GetSourceRowset,
557 server_Open,
558 server_SetColumns,
559 server_AddRefRows,
560 server_GetData,
561 server_GetNextRows,
562 server_ReleaseRows,
563 server_RestartPosition,
564 server_Compare,
565 server_GetRowsAt,
566 server_GetRowsByBookmark,
567 server_Hash,
568 server_GetProperties,
569 server_GetReferencedRowset,
570 server_GetSpecification,
571 server_AddRefAccessor,
572 server_CreateAccessor,
573 server_GetBindings,
574 server_ReleaseAccessor
577 static HRESULT create_server(IUnknown *outer, const CLSID *class, void **obj)
579 server *server;
580 TRACE("(%p, %s, %p)\n", outer, debugstr_guid(class), obj);
582 *obj = NULL;
584 server = HeapAlloc(GetProcessHeap(), 0, sizeof(*server));
585 if(!server) return E_OUTOFMEMORY;
587 server->IWineRowServer_iface.lpVtbl = &server_vtbl;
588 server->ref = 1;
589 server->class = *class;
590 server->inner_unk = NULL;
591 if(IsEqualGUID(class, &CLSID_wine_row_server))
592 create_row_marshal((IUnknown*)server, (void**)&server->marshal);
593 else if(IsEqualGUID(class, &CLSID_wine_rowset_server))
594 create_rowset_marshal((IUnknown*)server, (void**)&server->marshal);
595 else
596 ERR("create_server called with class %s\n", debugstr_guid(class));
598 *obj = server;
599 return S_OK;
602 HRESULT create_row_server(IUnknown *outer, void **obj)
604 return create_server(outer, &CLSID_wine_row_server, obj);
607 HRESULT create_rowset_server(IUnknown *outer, void **obj)
609 return create_server(outer, &CLSID_wine_rowset_server, obj);
612 typedef struct
614 IRow IRow_iface;
615 IRowChange IRowChange_iface;
617 LONG ref;
619 IWineRowServer *server;
620 } row_proxy;
622 static inline row_proxy *impl_from_IRow(IRow *iface)
624 return CONTAINING_RECORD(iface, row_proxy, IRow_iface);
627 static inline row_proxy *impl_from_IRowChange(IRowChange *iface)
629 return CONTAINING_RECORD(iface, row_proxy, IRowChange_iface);
632 static HRESULT WINAPI row_QueryInterface(IRow *iface, REFIID iid, void **obj)
634 row_proxy *This = impl_from_IRow(iface);
635 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(iid), obj);
637 if(IsEqualIID(iid, &IID_IUnknown) ||
638 IsEqualIID(iid, &IID_IRow))
640 *obj = &This->IRow_iface;
642 else if(IsEqualIID(iid, &IID_IRowChange))
644 *obj = &This->IRowChange_iface;
646 else
648 FIXME("interface %s not implemented\n", debugstr_guid(iid));
649 return E_NOINTERFACE;
652 IRow_AddRef(iface);
653 return S_OK;
656 static ULONG WINAPI row_AddRef(IRow *iface)
658 row_proxy *This = impl_from_IRow(iface);
659 TRACE("(%p)\n", This);
661 return InterlockedIncrement(&This->ref);
664 static ULONG WINAPI row_Release(IRow *iface)
666 row_proxy *This = impl_from_IRow(iface);
667 LONG ref;
669 TRACE("(%p)\n", This);
671 ref = InterlockedDecrement(&This->ref);
672 if(ref == 0)
674 if(This->server) IWineRowServer_Release(This->server);
675 HeapFree(GetProcessHeap(), 0, This);
678 return ref;
681 static HRESULT WINAPI row_GetColumns(IRow* iface, DBORDINAL cColumns, DBCOLUMNACCESS rgColumns[])
683 row_proxy *This = impl_from_IRow(iface);
684 DBORDINAL i;
685 wine_getcolumns_in *in_data;
686 wine_getcolumns_out *out_data;
687 HRESULT hr;
689 TRACE("(%p)->(%ld, %p)\n", This, cColumns, rgColumns);
691 in_data = CoTaskMemAlloc(cColumns * sizeof(in_data[0]));
692 out_data = CoTaskMemAlloc(cColumns * sizeof(out_data[0]));
694 for(i = 0; i < cColumns; i++)
696 TRACE("%ld:\tdata %p data_len %ld status %08x max_len %ld type %04x\n", i, rgColumns[i].pData,
697 rgColumns[i].cbDataLen, rgColumns[i].dwStatus, rgColumns[i].cbMaxLen, rgColumns[i].wType);
698 in_data[i].columnid = rgColumns[i].columnid;
699 in_data[i].max_len = rgColumns[i].cbMaxLen;
700 in_data[i].type = rgColumns[i].wType;
701 in_data[i].precision = rgColumns[i].bPrecision;
702 in_data[i].scale = rgColumns[i].bScale;
705 hr = IWineRowServer_GetColumns(This->server, cColumns, in_data, out_data);
707 for(i = 0; i < cColumns; i++)
709 rgColumns[i].cbDataLen = out_data[i].data_len;
710 rgColumns[i].dwStatus = out_data[i].status;
711 if(rgColumns[i].dwStatus == DBSTATUS_S_OK)
712 memcpy(rgColumns[i].pData, &V_I1(&out_data[i].v), out_data[i].data_len);
715 CoTaskMemFree(out_data);
716 CoTaskMemFree(in_data);
717 return hr;
720 static HRESULT WINAPI row_GetSourceRowset(IRow* iface, REFIID riid, IUnknown **ppRowset,
721 HROW *phRow)
723 row_proxy *This = impl_from_IRow(iface);
725 FIXME("(%p)->(%s, %p, %p): stub\n", This, debugstr_guid(riid), ppRowset, phRow);
727 return E_NOTIMPL;
730 static HRESULT WINAPI row_Open(IRow* iface, IUnknown *pUnkOuter,
731 DBID *pColumnID, REFGUID rguidColumnType,
732 DWORD dwBindFlags, REFIID riid, IUnknown **ppUnk)
734 row_proxy *This = impl_from_IRow(iface);
736 TRACE("(%p)->(%p, %p, %s, %08x, %s, %p)\n", This, pUnkOuter, pColumnID, debugstr_guid(rguidColumnType),
737 dwBindFlags, debugstr_guid(riid), ppUnk);
738 if(pUnkOuter)
740 FIXME("Aggregation not supported\n");
741 return CLASS_E_NOAGGREGATION;
744 return IWineRowServer_Open(This->server, pUnkOuter, pColumnID, rguidColumnType, dwBindFlags, riid, ppUnk);
747 static const IRowVtbl row_vtbl =
749 row_QueryInterface,
750 row_AddRef,
751 row_Release,
752 row_GetColumns,
753 row_GetSourceRowset,
754 row_Open
757 static HRESULT WINAPI row_change_QueryInterface(IRowChange *iface, REFIID iid, void **obj)
759 row_proxy *This = impl_from_IRowChange(iface);
760 return IUnknown_QueryInterface((IUnknown *)This, iid, obj);
763 static ULONG WINAPI row_change_AddRef(IRowChange *iface)
765 row_proxy *This = impl_from_IRowChange(iface);
766 return IUnknown_AddRef((IUnknown*)This);
769 static ULONG WINAPI row_change_Release(IRowChange *iface)
771 row_proxy *This = impl_from_IRowChange(iface);
772 return IUnknown_Release((IUnknown*)This);
775 static HRESULT WINAPI row_change_SetColumns(IRowChange *iface, DBORDINAL cColumns,
776 DBCOLUMNACCESS rgColumns[])
778 row_proxy *This = impl_from_IRowChange(iface);
779 HRESULT hr;
780 wine_setcolumns_in *in_data;
781 DBSTATUS *status;
782 DBORDINAL i;
784 TRACE("(%p)->(%ld, %p)\n", This, cColumns, rgColumns);
786 in_data = CoTaskMemAlloc(cColumns * sizeof(in_data[0]));
787 status = CoTaskMemAlloc(cColumns * sizeof(status[0]));
789 for(i = 0; i < cColumns; i++)
791 TRACE("%ld: wtype %04x max %08lx len %08lx\n", i, rgColumns[i].wType, rgColumns[i].cbMaxLen, rgColumns[i].cbDataLen);
792 V_VT(&in_data[i].v) = rgColumns[i].wType;
793 memcpy(&V_I1(&in_data[i].v), rgColumns[i].pData, db_type_size(rgColumns[i].wType, rgColumns[i].cbDataLen));
794 in_data[i].columnid = rgColumns[i].columnid;
795 in_data[i].data_len = rgColumns[i].cbDataLen;
796 in_data[i].status = rgColumns[i].dwStatus;
797 in_data[i].max_len = rgColumns[i].cbMaxLen;
798 in_data[i].type = rgColumns[i].wType;
799 in_data[i].precision = rgColumns[i].bPrecision;
800 in_data[i].scale = rgColumns[i].bScale;
803 hr = IWineRowServer_SetColumns(This->server, cColumns, in_data, status);
805 for(i = 0; i < cColumns; i++)
806 rgColumns[i].dwStatus = status[i];
808 CoTaskMemFree(status);
809 CoTaskMemFree(in_data);
811 return hr;
814 static const IRowChangeVtbl row_change_vtbl =
816 row_change_QueryInterface,
817 row_change_AddRef,
818 row_change_Release,
819 row_change_SetColumns
822 static HRESULT create_row_proxy(IWineRowServer *server, IUnknown **obj)
824 row_proxy *proxy;
826 TRACE("(%p, %p)\n", server, obj);
827 *obj = NULL;
829 proxy = HeapAlloc(GetProcessHeap(), 0, sizeof(*proxy));
830 if(!proxy) return E_OUTOFMEMORY;
832 proxy->IRow_iface.lpVtbl = &row_vtbl;
833 proxy->IRowChange_iface.lpVtbl = &row_change_vtbl;
834 proxy->ref = 1;
835 IWineRowServer_AddRef(server);
836 proxy->server = server;
838 *obj = (IUnknown*)&proxy->IRow_iface;
839 TRACE("returning %p\n", *obj);
840 return S_OK;
843 typedef struct
845 IRowsetLocate IRowsetLocate_iface;
846 IRowsetInfo IRowsetInfo_iface;
847 IAccessor IAccessor_iface;
849 LONG ref;
851 IWineRowServer *server;
852 } rowset_proxy;
854 static inline rowset_proxy *impl_from_IRowsetLocate(IRowsetLocate *iface)
856 return CONTAINING_RECORD(iface, rowset_proxy, IRowsetLocate_iface);
859 static inline rowset_proxy *impl_from_IRowsetInfo(IRowsetInfo *iface)
861 return CONTAINING_RECORD(iface, rowset_proxy, IRowsetInfo_iface);
864 static inline rowset_proxy *impl_from_IAccessor(IAccessor *iface)
866 return CONTAINING_RECORD(iface, rowset_proxy, IAccessor_iface);
869 static HRESULT WINAPI rowsetlocate_QueryInterface(IRowsetLocate *iface, REFIID iid, void **obj)
871 rowset_proxy *This = impl_from_IRowsetLocate(iface);
872 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(iid), obj);
874 *obj = NULL;
876 if(IsEqualIID(iid, &IID_IUnknown) ||
877 IsEqualIID(iid, &IID_IRowset) ||
878 IsEqualIID(iid, &IID_IRowsetLocate))
880 *obj = &This->IRowsetLocate_iface;
882 else if(IsEqualIID(iid, &IID_IRowsetInfo))
884 *obj = &This->IRowsetInfo_iface;
886 else if(IsEqualIID(iid, &IID_IAccessor))
888 *obj = &This->IAccessor_iface;
890 else
892 FIXME("interface %s not implemented\n", debugstr_guid(iid));
893 return E_NOINTERFACE;
896 IRowsetLocate_AddRef(iface);
897 return S_OK;
900 static ULONG WINAPI rowsetlocate_AddRef(IRowsetLocate *iface)
902 rowset_proxy *This = impl_from_IRowsetLocate(iface);
903 TRACE("(%p)\n", This);
905 return InterlockedIncrement(&This->ref);
908 static ULONG WINAPI rowsetlocate_Release(IRowsetLocate *iface)
910 rowset_proxy *This = impl_from_IRowsetLocate(iface);
911 LONG ref;
913 TRACE("(%p)\n", This);
915 ref = InterlockedDecrement(&This->ref);
916 if(ref == 0)
918 if(This->server) IWineRowServer_Release(This->server);
919 HeapFree(GetProcessHeap(), 0, This);
922 return ref;
925 static HRESULT WINAPI rowsetlocate_AddRefRows(IRowsetLocate *iface, DBCOUNTITEM cRows, const HROW rghRows[],
926 DBREFCOUNT rgRefCounts[], DBROWSTATUS rgRowStatus[])
928 rowset_proxy *This = impl_from_IRowsetLocate(iface);
929 HRESULT hr;
930 DBREFCOUNT *refs = rgRefCounts;
931 DBSTATUS *stats = rgRowStatus;
933 TRACE("(%p)->(%ld, %p, %p, %p)\n", This, cRows, rghRows, rgRefCounts, rgRowStatus);
935 if(!refs) refs = CoTaskMemAlloc(cRows * sizeof(refs[0]));
936 if(!stats) stats = CoTaskMemAlloc(cRows * sizeof(stats[0]));
938 hr = IWineRowServer_AddRefRows(This->server, cRows, rghRows, refs, stats);
940 if(refs != rgRefCounts) CoTaskMemFree(refs);
941 if(stats != rgRowStatus) CoTaskMemFree(stats);
943 return hr;
946 static HRESULT WINAPI rowsetlocate_GetData(IRowsetLocate *iface, HROW hRow, HACCESSOR hAccessor, void *pData)
948 rowset_proxy *This = impl_from_IRowsetLocate(iface);
949 HRESULT hr;
950 IAccessor *accessor;
951 DBACCESSORFLAGS flags;
952 DBCOUNTITEM count, i;
953 DBBINDING *bindings;
954 DWORD max_len = 0;
956 TRACE("(%p)->(%lx, %lx, %p)\n", This, hRow, hAccessor, pData);
958 hr = IRowsetLocate_QueryInterface(iface, &IID_IAccessor, (void**)&accessor);
959 if(FAILED(hr)) return hr;
961 hr = IAccessor_GetBindings(accessor, hAccessor, &flags, &count, &bindings);
962 IAccessor_Release(accessor);
963 if(FAILED(hr)) return hr;
965 TRACE("got %ld bindings\n", count);
966 for(i = 0; i < count; i++)
968 TRACE("%ld\tord %ld offs: val %ld len %ld stat %ld, part %x, max len %ld type %04x\n",
969 i, bindings[i].iOrdinal, bindings[i].obValue, bindings[i].obLength, bindings[i].obStatus,
970 bindings[i].dwPart, bindings[i].cbMaxLen, bindings[i].wType);
971 if(bindings[i].dwPart & DBPART_LENGTH && bindings[i].obLength >= max_len)
972 max_len = bindings[i].obLength + sizeof(DBLENGTH);
973 if(bindings[i].dwPart & DBPART_STATUS && bindings[i].obStatus >= max_len)
974 max_len = bindings[i].obStatus + sizeof(DWORD);
975 if(bindings[i].dwPart & DBPART_VALUE && bindings[i].obValue >= max_len)
976 max_len = bindings[i].obValue + db_type_size(bindings[i].wType, bindings[i].cbMaxLen);
979 TRACE("max_len %d\n", max_len);
981 CoTaskMemFree(bindings);
983 hr = IWineRowServer_GetData(This->server, hRow, hAccessor, pData, max_len);
985 return hr;
988 static HRESULT WINAPI rowsetlocate_GetNextRows(IRowsetLocate *iface, HCHAPTER hReserved, DBROWOFFSET lRowsOffset,
989 DBROWCOUNT cRows, DBCOUNTITEM *pcRowObtained, HROW **prghRows)
991 rowset_proxy *This = impl_from_IRowsetLocate(iface);
992 HRESULT hr;
993 HROW *rows = NULL;
995 TRACE("(%p)->(%08lx, %ld, %ld, %p, %p)\n", This, hReserved, lRowsOffset, cRows, pcRowObtained, prghRows);
997 hr = IWineRowServer_GetNextRows(This->server, hReserved, lRowsOffset, cRows, pcRowObtained, &rows);
998 if(*prghRows)
1000 memcpy(*prghRows, rows, *pcRowObtained * sizeof(rows[0]));
1001 CoTaskMemFree(rows);
1003 else
1004 *prghRows = rows;
1006 return hr;
1009 static HRESULT WINAPI rowsetlocate_ReleaseRows(IRowsetLocate *iface, DBCOUNTITEM cRows, const HROW rghRows[],
1010 DBROWOPTIONS rgRowOptions[], DBREFCOUNT rgRefCounts[], DBROWSTATUS rgRowStatus[])
1012 rowset_proxy *This = impl_from_IRowsetLocate(iface);
1013 HRESULT hr;
1014 DBROWOPTIONS *options = rgRowOptions;
1015 DBREFCOUNT *refs = rgRefCounts;
1016 DBROWSTATUS *status = rgRowStatus;
1018 TRACE("(%p)->(%ld, %p, %p, %p, %p)\n", This, cRows, rghRows, rgRowOptions, rgRefCounts, rgRowStatus);
1020 if(!options)
1022 options = CoTaskMemAlloc(cRows * sizeof(options[0]));
1023 memset(options, 0, cRows * sizeof(options[0]));
1025 if(!refs) refs = CoTaskMemAlloc(cRows * sizeof(refs[0]));
1026 if(!status) status = CoTaskMemAlloc(cRows * sizeof(status[0]));
1028 hr = IWineRowServer_ReleaseRows(This->server, cRows, rghRows, options, refs, status);
1030 if(status != rgRowStatus) CoTaskMemFree(status);
1031 if(refs != rgRefCounts) CoTaskMemFree(refs);
1032 if(options != rgRowOptions) CoTaskMemFree(options);
1034 return hr;
1037 static HRESULT WINAPI rowsetlocate_RestartPosition(IRowsetLocate* iface, HCHAPTER hReserved)
1039 rowset_proxy *This = impl_from_IRowsetLocate(iface);
1041 FIXME("(%p)->(%lx): stub\n", This, hReserved);
1043 return E_NOTIMPL;
1046 static HRESULT WINAPI rowsetlocate_Compare(IRowsetLocate *iface, HCHAPTER hReserved, DBBKMARK cbBookmark1, const BYTE *pBookmark1,
1047 DBBKMARK cbBookmark2, const BYTE *pBookmark2, DBCOMPARE *pComparison)
1049 rowset_proxy *This = impl_from_IRowsetLocate(iface);
1050 FIXME("(%p)\n", This);
1051 return E_NOTIMPL;
1054 static HRESULT WINAPI rowsetlocate_GetRowsAt(IRowsetLocate *iface, HWATCHREGION hReserved1, HCHAPTER hReserved2, DBBKMARK cbBookmark,
1055 const BYTE *pBookmark, DBROWOFFSET lRowsOffset, DBROWCOUNT cRows, DBCOUNTITEM *pcRowsObtained,
1056 HROW **prghRows)
1058 rowset_proxy *This = impl_from_IRowsetLocate(iface);
1059 HRESULT hr;
1060 HROW *rows = NULL;
1062 TRACE("(%p)->(%08lx, %08lx, %ld, %p, %ld, %ld, %p, %p\n", This, hReserved1, hReserved2, cbBookmark, pBookmark, lRowsOffset, cRows,
1063 pcRowsObtained, prghRows);
1065 hr = IWineRowServer_GetRowsAt(This->server, hReserved1, hReserved2, cbBookmark, pBookmark, lRowsOffset, cRows, pcRowsObtained, &rows);
1067 if(*prghRows)
1069 memcpy(*prghRows, rows, *pcRowsObtained * sizeof(rows[0]));
1070 CoTaskMemFree(rows);
1072 else
1073 *prghRows = rows;
1075 return hr;
1078 static HRESULT WINAPI rowsetlocate_GetRowsByBookmark(IRowsetLocate *iface, HCHAPTER hReserved, DBCOUNTITEM cRows, const DBBKMARK rgcbBookmarks[],
1079 const BYTE * rgpBookmarks[], HROW rghRows[], DBROWSTATUS rgRowStatus[])
1081 rowset_proxy *This = impl_from_IRowsetLocate(iface);
1082 FIXME("(%p)\n", This);
1083 return E_NOTIMPL;
1086 static HRESULT WINAPI rowsetlocate_Hash(IRowsetLocate *iface, HCHAPTER hReserved, DBBKMARK cBookmarks, const DBBKMARK rgcbBookmarks[],
1087 const BYTE * rgpBookmarks[], DBHASHVALUE rgHashedValues[], DBROWSTATUS rgBookmarkStatus[])
1089 rowset_proxy *This = impl_from_IRowsetLocate(iface);
1090 FIXME("(%p)\n", This);
1091 return E_NOTIMPL;
1094 static const IRowsetLocateVtbl rowsetlocate_vtbl =
1096 rowsetlocate_QueryInterface,
1097 rowsetlocate_AddRef,
1098 rowsetlocate_Release,
1099 rowsetlocate_AddRefRows,
1100 rowsetlocate_GetData,
1101 rowsetlocate_GetNextRows,
1102 rowsetlocate_ReleaseRows,
1103 rowsetlocate_RestartPosition,
1104 rowsetlocate_Compare,
1105 rowsetlocate_GetRowsAt,
1106 rowsetlocate_GetRowsByBookmark,
1107 rowsetlocate_Hash
1110 static HRESULT WINAPI rowsetinfo_QueryInterface(IRowsetInfo *iface, REFIID iid, void **obj)
1112 rowset_proxy *This = impl_from_IRowsetInfo(iface);
1113 return IUnknown_QueryInterface((IUnknown *)This, iid, obj);
1116 static ULONG WINAPI rowsetinfo_AddRef(IRowsetInfo *iface)
1118 rowset_proxy *This = impl_from_IRowsetInfo(iface);
1119 return IUnknown_AddRef((IUnknown *)This);
1122 static ULONG WINAPI rowsetinfo_Release(IRowsetInfo *iface)
1124 rowset_proxy *This = impl_from_IRowsetInfo(iface);
1125 return IUnknown_Release((IUnknown *)This);
1128 static HRESULT WINAPI rowsetinfo_GetProperties(IRowsetInfo *iface, const ULONG cPropertyIDSets,
1129 const DBPROPIDSET rgPropertyIDSets[], ULONG *pcPropertySets,
1130 DBPROPSET **prgPropertySets)
1132 rowset_proxy *This = impl_from_IRowsetInfo(iface);
1133 HRESULT hr;
1135 TRACE("(%p)->(%d, %p, %p, %p)\n", This, cPropertyIDSets, rgPropertyIDSets, pcPropertySets, prgPropertySets);
1137 hr = IWineRowServer_GetProperties(This->server, cPropertyIDSets, rgPropertyIDSets, pcPropertySets, prgPropertySets);
1139 return hr;
1142 static HRESULT WINAPI rowsetinfo_GetReferencedRowset(IRowsetInfo *iface, DBORDINAL iOrdinal, REFIID riid,
1143 IUnknown **ppReferencedRowset)
1145 rowset_proxy *This = impl_from_IRowsetInfo(iface);
1146 FIXME("(%p)\n", This);
1147 return E_NOTIMPL;
1150 static HRESULT WINAPI rowsetinfo_GetSpecification(IRowsetInfo *iface, REFIID riid, IUnknown **ppSpecification)
1152 rowset_proxy *This = impl_from_IRowsetInfo(iface);
1153 FIXME("(%p)\n", This);
1154 return E_NOTIMPL;
1157 static const IRowsetInfoVtbl rowsetinfo_vtbl =
1159 rowsetinfo_QueryInterface,
1160 rowsetinfo_AddRef,
1161 rowsetinfo_Release,
1162 rowsetinfo_GetProperties,
1163 rowsetinfo_GetReferencedRowset,
1164 rowsetinfo_GetSpecification
1167 static HRESULT WINAPI accessor_QueryInterface(IAccessor *iface, REFIID iid, void **obj)
1169 rowset_proxy *This = impl_from_IAccessor(iface);
1170 return IUnknown_QueryInterface((IUnknown *)This, iid, obj);
1173 static ULONG WINAPI accessor_AddRef(IAccessor *iface)
1175 rowset_proxy *This = impl_from_IAccessor(iface);
1176 return IUnknown_AddRef((IUnknown *)This);
1179 static ULONG WINAPI accessor_Release(IAccessor *iface)
1181 rowset_proxy *This = impl_from_IAccessor(iface);
1182 return IUnknown_Release((IUnknown *)This);
1185 static HRESULT WINAPI accessor_AddRefAccessor(IAccessor *iface, HACCESSOR hAccessor, DBREFCOUNT *pcRefCount)
1187 rowset_proxy *This = impl_from_IAccessor(iface);
1188 FIXME("(%p)\n", This);
1189 return E_NOTIMPL;
1192 static HRESULT WINAPI accessor_CreateAccessor(IAccessor *iface, DBACCESSORFLAGS dwAccessorFlags, DBCOUNTITEM cBindings,
1193 const DBBINDING rgBindings[], DBLENGTH cbRowSize, HACCESSOR *phAccessor,
1194 DBBINDSTATUS rgStatus[])
1196 rowset_proxy *This = impl_from_IAccessor(iface);
1197 HRESULT hr;
1198 DBBINDSTATUS *status;
1200 TRACE("(%p)->(%08x, %ld, %p, %ld, %p, %p)\n", This, dwAccessorFlags, cBindings, rgBindings, cbRowSize, phAccessor, rgStatus);
1202 if(!rgStatus) status = CoTaskMemAlloc(cBindings * sizeof(status[0]));
1203 else status = rgStatus;
1205 hr = IWineRowServer_CreateAccessor(This->server, dwAccessorFlags, cBindings, rgBindings, cbRowSize, phAccessor, status);
1207 if(!rgStatus) CoTaskMemFree(status);
1209 return hr;
1212 static HRESULT WINAPI accessor_GetBindings(IAccessor *iface, HACCESSOR hAccessor, DBACCESSORFLAGS *pdwAccessorFlags,
1213 DBCOUNTITEM *pcBindings, DBBINDING **prgBindings)
1215 rowset_proxy *This = impl_from_IAccessor(iface);
1216 HRESULT hr;
1218 TRACE("(%p)->(%08lx, %p, %p, %p)\n", This, hAccessor, pdwAccessorFlags, pcBindings, prgBindings);
1220 hr = IWineRowServer_GetBindings(This->server, hAccessor, pdwAccessorFlags, pcBindings, prgBindings);
1222 return hr;
1225 static HRESULT WINAPI accessor_ReleaseAccessor(IAccessor *iface, HACCESSOR hAccessor, DBREFCOUNT *pcRefCount)
1227 rowset_proxy *This = impl_from_IAccessor(iface);
1228 HRESULT hr;
1229 DBREFCOUNT ref;
1231 TRACE("(%p)->(%08lx, %p)\n", This, hAccessor, pcRefCount);
1233 hr = IWineRowServer_ReleaseAccessor(This->server, hAccessor, &ref);
1234 if(pcRefCount) *pcRefCount = ref;
1235 return hr;
1238 static const IAccessorVtbl accessor_vtbl =
1240 accessor_QueryInterface,
1241 accessor_AddRef,
1242 accessor_Release,
1243 accessor_AddRefAccessor,
1244 accessor_CreateAccessor,
1245 accessor_GetBindings,
1246 accessor_ReleaseAccessor
1249 static HRESULT create_rowset_proxy(IWineRowServer *server, IUnknown **obj)
1251 rowset_proxy *proxy;
1253 TRACE("(%p, %p)\n", server, obj);
1254 *obj = NULL;
1256 proxy = HeapAlloc(GetProcessHeap(), 0, sizeof(*proxy));
1257 if(!proxy) return E_OUTOFMEMORY;
1259 proxy->IRowsetLocate_iface.lpVtbl = &rowsetlocate_vtbl;
1260 proxy->IRowsetInfo_iface.lpVtbl = &rowsetinfo_vtbl;
1261 proxy->IAccessor_iface.lpVtbl = &accessor_vtbl;
1262 proxy->ref = 1;
1263 IWineRowServer_AddRef(server);
1264 proxy->server = server;
1266 *obj = (IUnknown *)&proxy->IRowsetLocate_iface;
1267 TRACE("returning %p\n", *obj);
1268 return S_OK;
1271 static HRESULT create_proxy(IWineRowServer *server, const CLSID *class, IUnknown **obj)
1273 *obj = NULL;
1275 if(IsEqualGUID(class, &CLSID_wine_row_proxy))
1276 return create_row_proxy(server, obj);
1277 else if(IsEqualGUID(class, &CLSID_wine_rowset_proxy))
1278 return create_rowset_proxy(server, obj);
1279 else
1280 FIXME("Unhandled proxy class %s\n", debugstr_guid(class));
1281 return E_NOTIMPL;
1284 /* Marshal impl */
1286 typedef struct
1288 IMarshal IMarshal_iface;
1290 LONG ref;
1291 CLSID unmarshal_class;
1292 IUnknown *outer;
1293 } marshal;
1295 static inline marshal *impl_from_IMarshal(IMarshal *iface)
1297 return CONTAINING_RECORD(iface, marshal, IMarshal_iface);
1300 static HRESULT WINAPI marshal_QueryInterface(IMarshal *iface, REFIID iid, void **obj)
1302 marshal *This = impl_from_IMarshal(iface);
1303 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(iid), obj);
1305 if(IsEqualIID(iid, &IID_IUnknown) ||
1306 IsEqualIID(iid, &IID_IMarshal))
1308 *obj = iface;
1310 else
1312 FIXME("interface %s not implemented\n", debugstr_guid(iid));
1313 *obj = NULL;
1314 return E_NOINTERFACE;
1317 IMarshal_AddRef(iface);
1318 return S_OK;
1321 static ULONG WINAPI marshal_AddRef(IMarshal *iface)
1323 marshal *This = impl_from_IMarshal(iface);
1324 TRACE("(%p)\n", This);
1325 return InterlockedIncrement(&This->ref);
1328 static ULONG WINAPI marshal_Release(IMarshal *iface)
1330 marshal *This = impl_from_IMarshal(iface);
1331 LONG ref;
1333 TRACE("(%p)\n", This);
1335 ref = InterlockedDecrement(&This->ref);
1336 if(ref == 0)
1338 HeapFree(GetProcessHeap(), 0, This);
1341 return ref;
1344 static HRESULT WINAPI marshal_GetUnmarshalClass(IMarshal *iface, REFIID iid, void *obj,
1345 DWORD dwDestContext, void *pvDestContext,
1346 DWORD mshlflags, CLSID *clsid)
1348 marshal *This = impl_from_IMarshal(iface);
1349 TRACE("(%p)->(%s, %p, %08x, %p, %08x, %p)\n", This, debugstr_guid(iid), obj, dwDestContext,
1350 pvDestContext, mshlflags, clsid);
1352 *clsid = This->unmarshal_class;
1353 return S_OK;
1356 static HRESULT WINAPI marshal_GetMarshalSizeMax(IMarshal *iface, REFIID iid, void *obj,
1357 DWORD dwDestContext, void *pvDestContext,
1358 DWORD mshlflags, DWORD *size)
1360 marshal *This = impl_from_IMarshal(iface);
1361 TRACE("(%p)->(%s, %p, %08x, %p, %08x, %p)\n", This, debugstr_guid(iid), obj, dwDestContext,
1362 pvDestContext, mshlflags, size);
1364 return CoGetMarshalSizeMax(size, &IID_IWineRowServer, This->outer, dwDestContext, pvDestContext,
1365 mshlflags);
1368 static HRESULT WINAPI marshal_MarshalInterface(IMarshal *iface, IStream *stream, REFIID iid,
1369 void *obj, DWORD dwDestContext, void *pvDestContext,
1370 DWORD mshlflags)
1372 marshal *This = impl_from_IMarshal(iface);
1373 TRACE("(%p)->(%p, %s, %p, %08x, %p, %08x)\n", This, stream, debugstr_guid(iid), obj, dwDestContext,
1374 pvDestContext, mshlflags);
1376 return CoMarshalInterface(stream, &IID_IWineRowServer, This->outer, dwDestContext, pvDestContext, mshlflags);
1379 static HRESULT WINAPI marshal_UnmarshalInterface(IMarshal *iface, IStream *stream,
1380 REFIID iid, void **obj)
1382 marshal *This = impl_from_IMarshal(iface);
1383 HRESULT hr;
1384 IWineRowServer *server;
1385 IUnknown *proxy;
1387 TRACE("(%p)->(%p, %s, %p)\n", This, stream, debugstr_guid(iid), obj);
1388 *obj = NULL;
1390 hr = CoUnmarshalInterface(stream, &IID_IWineRowServer, (void**)&server);
1391 if(SUCCEEDED(hr))
1393 hr = create_proxy(server, &This->unmarshal_class, &proxy);
1394 if(SUCCEEDED(hr))
1396 hr = IUnknown_QueryInterface(proxy, iid, obj);
1397 IUnknown_Release(proxy);
1399 IWineRowServer_Release(server);
1402 TRACE("returning %p\n", *obj);
1403 return hr;
1406 static HRESULT WINAPI marshal_ReleaseMarshalData(IMarshal *iface, IStream *stream)
1408 marshal *This = impl_from_IMarshal(iface);
1409 TRACE("(%p)->(%p)\n", This, stream);
1410 return CoReleaseMarshalData(stream);
1413 static HRESULT WINAPI marshal_DisconnectObject(IMarshal *iface, DWORD dwReserved)
1415 marshal *This = impl_from_IMarshal(iface);
1416 FIXME("(%p)->(%08x)\n", This, dwReserved);
1418 return E_NOTIMPL;
1421 static const IMarshalVtbl marshal_vtbl =
1423 marshal_QueryInterface,
1424 marshal_AddRef,
1425 marshal_Release,
1426 marshal_GetUnmarshalClass,
1427 marshal_GetMarshalSizeMax,
1428 marshal_MarshalInterface,
1429 marshal_UnmarshalInterface,
1430 marshal_ReleaseMarshalData,
1431 marshal_DisconnectObject
1434 static HRESULT create_marshal(IUnknown *outer, const CLSID *class, void **obj)
1436 marshal *marshal;
1438 TRACE("(%p, %p)\n", outer, obj);
1439 *obj = NULL;
1441 marshal = HeapAlloc(GetProcessHeap(), 0, sizeof(*marshal));
1442 if(!marshal) return E_OUTOFMEMORY;
1444 marshal->unmarshal_class = *class;
1445 marshal->outer = outer; /* don't ref outer unk */
1446 marshal->IMarshal_iface.lpVtbl = &marshal_vtbl;
1447 marshal->ref = 1;
1449 *obj = &marshal->IMarshal_iface;
1450 TRACE("returning %p\n", *obj);
1451 return S_OK;
1454 HRESULT create_row_marshal(IUnknown *outer, void **obj)
1456 TRACE("(%p, %p)\n", outer, obj);
1457 return create_marshal(outer, &CLSID_wine_row_proxy, obj);
1460 HRESULT create_rowset_marshal(IUnknown *outer, void **obj)
1462 TRACE("(%p, %p)\n", outer, obj);
1463 return create_marshal(outer, &CLSID_wine_rowset_proxy, obj);