~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/msdaps/row_server.c

Version: ~ [ wine-1.5.4 ] ~ [ wine-1.5.3 ] ~ [ wine-1.5.2 ] ~ [ wine-1.5.1 ] ~ [ wine-1.5.0 ] ~ [ wine-1.4 ] ~ [ wine-1.4-rc6 ] ~ [ wine-1.4-rc5 ] ~ [ wine-1.4-rc4 ] ~ [ wine-1.4-rc3 ] ~ [ wine-1.4-rc2 ] ~ [ wine-1.4-rc1 ] ~ [ wine-1.3.37 ] ~ [ wine-1.3.36 ] ~ [ wine-1.3.35 ] ~ [ wine-1.3.34 ] ~ [ wine-1.3.33 ] ~ [ wine-1.3.32 ] ~ [ wine-1.3.31 ] ~ [ wine-1.3.30 ] ~ [ wine-1.3.29 ] ~ [ wine-1.3.28 ] ~ [ wine-1.3.27 ] ~ [ wine-1.3.26 ] ~ [ wine-1.3.25 ] ~ [ wine-1.3.24 ] ~ [ wine-1.3.23 ] ~ [ wine-1.3.22 ] ~ [ wine-1.3.21 ] ~ [ wine-1.3.20 ] ~ [ wine-1.3.19 ] ~ [ wine-1.3.18 ] ~ [ wine-1.2.3 ] ~ [ wine-1.3.17 ] ~ [ wine-1.3.16 ] ~ [ wine-1.3.15 ] ~ [ wine-1.3.14 ] ~ [ wine-1.3.13 ] ~ [ wine-1.3.12 ] ~ [ wine-1.3.11 ] ~ [ wine-1.3.10 ] ~ [ wine-1.3.9 ] ~ [ wine-1.2.2 ] ~ [ wine-1.3.8 ] ~ [ wine-1.3.7 ] ~ [ wine-1.3.6 ] ~ [ wine-1.3.5 ] ~ [ wine-1.2.1 ] ~ [ wine-1.3.4 ] ~ [ wine-1.3.3 ] ~ [ wine-1.3.2 ] ~ [ wine-1.3.1 ] ~ [ wine-1.3.0 ] ~ [ wine-1.2 ] ~ [ wine-1.2-rc7 ] ~ [ wine-1.2-rc6 ] ~ [ wine-1.2-rc5 ] ~ [ wine-1.2-rc4 ] ~ [ wine-1.2-rc3 ] ~ [ wine-1.2-rc2 ] ~ [ wine-1.2-rc1 ] ~ [ wine-1.1.44 ] ~ [ wine-1.1.43 ] ~ [ wine-1.1.42 ] ~ [ wine-1.1.41 ] ~ [ wine-1.1.40 ] ~ [ wine-1.1.39 ] ~ [ wine-1.1.38 ] ~ [ wine-1.1.37 ] ~ [ wine-1.1.36 ] ~ [ wine-1.1.35 ] ~ [ wine-1.1.34 ] ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*
  2  *    Row and rowset servers / proxies.
  3  *
  4  * Copyright 2010 Huw Davies
  5  *
  6  * This library is free software; you can redistribute it and/or
  7  * modify it under the terms of the GNU Lesser General Public
  8  * License as published by the Free Software Foundation; either
  9  * version 2.1 of the License, or (at your option) any later version.
 10  *
 11  * This library is distributed in the hope that it will be useful,
 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 14  * Lesser General Public License for more details.
 15  *
 16  * You should have received a copy of the GNU Lesser General Public
 17  * License along with this library; if not, write to the Free Software
 18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 19  */
 20 #include <stdarg.h>
 21 #include <string.h>
 22 
 23 #define COBJMACROS
 24 #define NONAMELESSUNION
 25 #define NONAMELESSSTRUCT
 26 
 27 #include "windef.h"
 28 #include "winbase.h"
 29 #include "wingdi.h"
 30 #include "winuser.h"
 31 #include "winerror.h"
 32 #include "objbase.h"
 33 #include "oleauto.h"
 34 #include "oledb.h"
 35 
 36 #include "row_server.h"
 37 
 38 #include "wine/debug.h"
 39 
 40 WINE_DEFAULT_DEBUG_CHANNEL(oledb);
 41 
 42 static inline DBLENGTH db_type_size(DBTYPE type, DBLENGTH var_len)
 43 {
 44     switch(type)
 45     {
 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;
 73     }
 74 }
 75 
 76 typedef struct
 77 {
 78     IWineRowServer IWineRowServer_iface;
 79 
 80     LONG ref;
 81 
 82     CLSID class;
 83     IMarshal *marshal;
 84     IUnknown *inner_unk;
 85 } server;
 86 
 87 static inline server *impl_from_IWineRowServer(IWineRowServer *iface)
 88 {
 89     return CONTAINING_RECORD(iface, server, IWineRowServer_iface);
 90 }
 91 
 92 static HRESULT WINAPI server_QueryInterface(IWineRowServer *iface, REFIID riid, void **obj)
 93 {
 94     server *This = impl_from_IWineRowServer(iface);
 95     TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), obj);
 96 
 97     *obj = NULL;
 98 
 99     if(IsEqualIID(riid, &IID_IUnknown) ||
100        IsEqualIID(riid, &IID_IWineRowServer))
101     {
102         *obj = iface;
103     }
104     else
105     {
106         if(!IsEqualIID(riid, &IID_IMarshal)) /* We use standard marshalling */
107             FIXME("interface %s not implemented\n", debugstr_guid(riid));
108         return E_NOINTERFACE;
109     }
110 
111     IWineRowServer_AddRef(iface);
112     return S_OK;
113 }
114 
115 static ULONG WINAPI server_AddRef(IWineRowServer *iface)
116 {
117     server *This = impl_from_IWineRowServer(iface);
118     TRACE("(%p)\n", This);
119 
120     return InterlockedIncrement(&This->ref);
121 }
122 
123 static ULONG WINAPI server_Release(IWineRowServer *iface)
124 {
125     server *This = impl_from_IWineRowServer(iface);
126     LONG ref;
127 
128     TRACE("(%p)\n", This);
129 
130     ref = InterlockedDecrement(&This->ref);
131     if(ref == 0)
132     {
133         IMarshal_Release(This->marshal);
134         if(This->inner_unk) IUnknown_Release(This->inner_unk);
135         HeapFree(GetProcessHeap(), 0, This);
136     }
137 
138     return ref;
139 }
140 
141 static HRESULT WINAPI server_SetInnerUnk(IWineRowServer *iface, IUnknown *inner)
142 {
143     server *This = impl_from_IWineRowServer(iface);
144 
145     if(This->inner_unk) IUnknown_Release(This->inner_unk);
146 
147     if(inner) IUnknown_AddRef(inner);
148     This->inner_unk = inner;
149     return S_OK;
150 }
151 
152 static HRESULT WINAPI server_GetMarshal(IWineRowServer *iface, IMarshal **marshal)
153 {
154     server *This = impl_from_IWineRowServer(iface);
155 
156     IMarshal_AddRef(This->marshal);
157     *marshal = This->marshal;
158     return S_OK;
159 }
160 
161 static HRESULT WINAPI server_GetColumns(IWineRowServer* iface, DBORDINAL num_cols,
162                                         wine_getcolumns_in *in_data, wine_getcolumns_out *out_data)
163 {
164     server *This = impl_from_IWineRowServer(iface);
165     HRESULT hr;
166     DBORDINAL i;
167     DBCOLUMNACCESS *cols;
168     IRow *row;
169 
170     TRACE("(%p)->(%ld, %p, %p)\n", This, num_cols, in_data, out_data);
171 
172     hr = IUnknown_QueryInterface(This->inner_unk, &IID_IRow, (void**)&row);
173     if(FAILED(hr)) return hr;
174 
175     cols = CoTaskMemAlloc(num_cols * sizeof(cols[0]));
176 
177     for(i = 0; i < num_cols; i++)
178     {
179         TRACE("%ld:\tmax_len %ld type %04x\n", i, in_data[i].max_len, in_data[i].type);
180         cols[i].pData        = CoTaskMemAlloc(db_type_size(in_data[i].type, in_data[i].max_len));
181         cols[i].columnid     = in_data[i].columnid;
182         cols[i].cbMaxLen     = in_data[i].max_len;
183         cols[i].wType        = in_data[i].type;
184         cols[i].bPrecision   = in_data[i].precision;
185         cols[i].bScale       = in_data[i].scale;
186     }
187 
188     hr = IRow_GetColumns(row, num_cols, cols);
189     IRow_Release(row);
190 
191     for(i = 0; i < num_cols; i++)
192     {
193         VariantInit(&out_data[i].v);
194         if(cols[i].dwStatus == DBSTATUS_S_OK)
195         {
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);
198         }
199         CoTaskMemFree(cols[i].pData);
200         out_data[i].data_len = cols[i].cbDataLen;
201         out_data[i].status   = cols[i].dwStatus;
202     }
203 
204     CoTaskMemFree(cols);
205 
206     return hr;
207 }
208 
209 static HRESULT WINAPI server_GetSourceRowset(IWineRowServer* iface, REFIID riid, IUnknown **ppRowset,
210                                              HROW *phRow)
211 {
212     server *This = impl_from_IWineRowServer(iface);
213     FIXME("(%p): stub\n", This);
214     return E_NOTIMPL;
215 }
216 
217 static HRESULT WINAPI server_Open(IWineRowServer* iface, IUnknown *pUnkOuter, DBID *pColumnID,
218                                   REFGUID rguidColumnType, DWORD dwBindFlags, REFIID riid,
219                                   IUnknown **ppUnk)
220 {
221     server *This = impl_from_IWineRowServer(iface);
222     IRow *row;
223     HRESULT hr;
224     IWineRowServer *new_server;
225     IMarshal *marshal;
226     IUnknown *obj;
227 
228     TRACE("(%p)->(%p, %p, %s, %08x, %s, %p)\n", This, pUnkOuter, pColumnID, debugstr_guid(rguidColumnType),
229           dwBindFlags, debugstr_guid(riid), ppUnk);
230 
231     *ppUnk = NULL;
232 
233     hr = IUnknown_QueryInterface(This->inner_unk, &IID_IRow, (void**)&row);
234     if(FAILED(hr)) return hr;
235 
236     if(IsEqualGUID(rguidColumnType, &DBGUID_ROWSET))
237         hr = CoCreateInstance(&CLSID_wine_rowset_server, NULL, CLSCTX_INPROC_SERVER, &IID_IWineRowServer, (void**)&new_server);
238     else
239     {
240         FIXME("Unhandled object %s\n", debugstr_guid(rguidColumnType));
241         hr = E_NOTIMPL;
242     }
243 
244     if(FAILED(hr))
245     {
246         IRow_Release(row);
247         return hr;
248     }
249 
250     IWineRowServer_GetMarshal(new_server, &marshal);
251     hr = IRow_Open(row, (IUnknown*)marshal, pColumnID, rguidColumnType, dwBindFlags, &IID_IUnknown, &obj);
252     IMarshal_Release(marshal);
253     IRow_Release(row);
254 
255     if(FAILED(hr))
256     {
257         IWineRowServer_Release(new_server);
258         return hr;
259     }
260 
261     IWineRowServer_SetInnerUnk(new_server, obj);
262     hr = IUnknown_QueryInterface(obj, riid, (void**)ppUnk);
263     IUnknown_Release(obj);
264 
265     TRACE("returning %08x\n", hr);
266     return hr;
267 }
268 
269 static HRESULT WINAPI server_SetColumns(IWineRowServer* iface, DBORDINAL num_cols,
270                                         wine_setcolumns_in *in_data, DBSTATUS *status)
271 {
272     server *This = impl_from_IWineRowServer(iface);
273     HRESULT hr;
274     DBORDINAL i;
275     DBCOLUMNACCESS *cols;
276     IRowChange *row_change;
277 
278     TRACE("(%p)->(%ld, %p, %p)\n", This, num_cols, in_data, status);
279     hr = IUnknown_QueryInterface(This->inner_unk, &IID_IRowChange, (void**)&row_change);
280     if(FAILED(hr)) return hr;
281 
282     cols = CoTaskMemAlloc(num_cols * sizeof(cols[0]));
283 
284     for(i = 0; i < num_cols; i++)
285     {
286         TRACE("%ld:\ttype %04x\n", i, in_data[i].type);
287         cols[i].pData        = CoTaskMemAlloc(db_type_size(in_data[i].type, in_data[i].max_len));
288         memcpy(cols[i].pData, &V_I1(&in_data[i].v), db_type_size(in_data[i].type, in_data[i].max_len));
289         cols[i].columnid     = in_data[i].columnid;
290         cols[i].cbDataLen    = in_data[i].data_len;
291         cols[i].dwStatus     = in_data[i].status;
292         cols[i].cbMaxLen     = in_data[i].max_len;
293         cols[i].wType        = in_data[i].type;
294         cols[i].bPrecision   = in_data[i].precision;
295         cols[i].bScale       = in_data[i].scale;
296     }
297 
298     hr = IRowChange_SetColumns(row_change, num_cols, cols);
299     IRowChange_Release(row_change);
300 
301     for(i = 0; i < num_cols; i++)
302     {
303         CoTaskMemFree(cols[i].pData);
304         status[i] = cols[i].dwStatus;
305     }
306 
307     CoTaskMemFree(cols);
308 
309     return hr;
310 }
311 
312 static HRESULT WINAPI server_AddRefRows(IWineRowServer* iface, DBCOUNTITEM cRows,
313                                         const HROW rghRows[], DBREFCOUNT rgRefCounts[],
314                                         DBROWSTATUS rgRowStatus[])
315 {
316     server *This = impl_from_IWineRowServer(iface);
317     IRowset *rowset;
318     HRESULT hr;
319 
320     TRACE("(%p)->(%ld, %p, %p, %p)\n", This, cRows, rghRows, rgRefCounts, rgRowStatus);
321 
322     hr = IUnknown_QueryInterface(This->inner_unk, &IID_IRowset, (void**)&rowset);
323     if(FAILED(hr)) return hr;
324 
325     hr = IRowset_AddRefRows(rowset, cRows, rghRows, rgRefCounts, rgRowStatus);
326 
327     IRowset_Release(rowset);
328     TRACE("returning %08x\n", hr);
329     return hr;
330 }
331 
332 static HRESULT WINAPI server_GetData(IWineRowServer* iface, HROW hRow,
333                                      HACCESSOR hAccessor, BYTE *pData, DWORD size)
334 {
335     server *This = impl_from_IWineRowServer(iface);
336     IRowset *rowset;
337     HRESULT hr;
338 
339     TRACE("(%p)->(%08lx, %08lx, %p, %d)\n", This, hRow, hAccessor, pData, size);
340 
341     hr = IUnknown_QueryInterface(This->inner_unk, &IID_IRowset, (void**)&rowset);
342     if(FAILED(hr)) return hr;
343 
344     hr = IRowset_GetData(rowset, hRow, hAccessor, pData);
345 
346     IRowset_Release(rowset);
347     TRACE("returning %08x\n", hr);
348     return hr;
349 }
350 
351 static HRESULT WINAPI server_GetNextRows(IWineRowServer* iface, HCHAPTER hReserved, DBROWOFFSET lRowsOffset,
352                                          DBROWCOUNT cRows, DBCOUNTITEM *pcRowObtained, HROW **prghRows)
353 {
354     server *This = impl_from_IWineRowServer(iface);
355     IRowset *rowset;
356     HRESULT hr;
357 
358     TRACE("(%p)->(%08lx, %ld, %ld, %p, %p)\n", This, hReserved, lRowsOffset, cRows, pcRowObtained, prghRows);
359 
360     hr = IUnknown_QueryInterface(This->inner_unk, &IID_IRowset, (void**)&rowset);
361     if(FAILED(hr)) return hr;
362 
363     *prghRows = NULL;
364 
365     hr = IRowset_GetNextRows(rowset, hReserved, lRowsOffset, cRows, pcRowObtained, prghRows);
366     IRowset_Release(rowset);
367     TRACE("returning %08x, got %ld rows\n", hr, *pcRowObtained);
368     return hr;
369 }
370 
371 static HRESULT WINAPI server_ReleaseRows(IWineRowServer* iface, DBCOUNTITEM cRows, const HROW rghRows[],
372                                          DBROWOPTIONS rgRowOptions[], DBREFCOUNT rgRefCounts[], DBROWSTATUS rgRowStatus[])
373 {
374     server *This = impl_from_IWineRowServer(iface);
375     IRowset *rowset;
376     HRESULT hr;
377 
378     TRACE("(%p)->(%ld, %p, %p, %p, %p)\n", This, cRows, rghRows, rgRowOptions, rgRefCounts, rgRowStatus);
379 
380     hr = IUnknown_QueryInterface(This->inner_unk, &IID_IRowset, (void**)&rowset);
381     if(FAILED(hr)) return hr;
382 
383     hr = IRowset_ReleaseRows(rowset, cRows, rghRows, rgRowOptions, rgRefCounts, rgRowStatus);
384     IRowset_Release(rowset);
385 
386     TRACE("returning %08x\n", hr);
387     return hr;
388 }
389 
390 static HRESULT WINAPI server_RestartPosition(IWineRowServer* iface, HCHAPTER hReserved)
391 {
392     server *This = impl_from_IWineRowServer(iface);
393     FIXME("(%p)->(%08lx): stub\n", This, hReserved);
394     return E_NOTIMPL;
395 }
396 
397 static HRESULT WINAPI server_Compare(IWineRowServer *iface, HCHAPTER hReserved, DBBKMARK cbBookmark1,
398                                      const BYTE *pBookmark1, DBBKMARK cbBookmark2, const BYTE *pBookmark2,
399                                      DBCOMPARE *pComparison)
400 {
401     server *This = impl_from_IWineRowServer(iface);
402     FIXME("(%p): stub\n", This);
403     return E_NOTIMPL;
404 }
405 
406 static HRESULT WINAPI server_GetRowsAt(IWineRowServer *iface, HWATCHREGION hReserved1, HCHAPTER hReserved2,
407                                        DBBKMARK cbBookmark, const BYTE *pBookmark, DBROWOFFSET lRowsOffset,
408                                        DBROWCOUNT cRows, DBCOUNTITEM *pcRowsObtained, HROW **prghRows)
409 {
410     server *This = impl_from_IWineRowServer(iface);
411     IRowsetLocate *rowsetlocate;
412     HRESULT hr;
413 
414     TRACE("(%p)->(%08lx, %08lx, %ld, %p, %ld, %ld, %p, %p\n", This, hReserved1, hReserved2, cbBookmark, pBookmark, lRowsOffset, cRows,
415           pcRowsObtained, prghRows);
416 
417     *prghRows = NULL;
418 
419     hr = IUnknown_QueryInterface(This->inner_unk, &IID_IRowsetLocate, (void**)&rowsetlocate);
420     if(FAILED(hr)) return hr;
421 
422     hr = IRowsetLocate_GetRowsAt(rowsetlocate, hReserved1, hReserved2, cbBookmark, pBookmark, lRowsOffset,
423                                  cRows, pcRowsObtained, prghRows);
424     IRowsetLocate_Release(rowsetlocate);
425 
426     TRACE("returning %08x\n", hr);
427     return hr;
428 }
429 
430 static HRESULT WINAPI server_GetRowsByBookmark(IWineRowServer *iface, HCHAPTER hReserved, DBCOUNTITEM cRows,
431                                                const DBBKMARK rgcbBookmarks[], const BYTE * rgpBookmarks[],
432                                                HROW rghRows[], DBROWSTATUS rgRowStatus[])
433 {
434     server *This = impl_from_IWineRowServer(iface);
435     FIXME("(%p): stub\n", This);
436     return E_NOTIMPL;
437 }
438 
439 static HRESULT WINAPI server_Hash(IWineRowServer *iface, HCHAPTER hReserved, DBBKMARK cBookmarks,
440                                   const DBBKMARK rgcbBookmarks[], const BYTE * rgpBookmarks[],
441                                   DBHASHVALUE rgHashedValues[], DBROWSTATUS rgBookmarkStatus[])
442 {
443     server *This = impl_from_IWineRowServer(iface);
444     FIXME("(%p): stub\n", This);
445     return E_NOTIMPL;
446 }
447 
448 static HRESULT WINAPI server_GetProperties(IWineRowServer* iface, ULONG cPropertyIDSets,
449                                            const DBPROPIDSET *rgPropertyIDSets, ULONG *pcPropertySets,
450                                            DBPROPSET **prgPropertySets)
451 {
452     server *This = impl_from_IWineRowServer(iface);
453     IRowsetInfo *rowsetinfo;
454     HRESULT hr;
455 
456     TRACE("(%p)->(%d, %p, %p, %p)\n", This, cPropertyIDSets, rgPropertyIDSets, pcPropertySets, prgPropertySets);
457 
458     hr = IUnknown_QueryInterface(This->inner_unk, &IID_IRowsetInfo, (void**)&rowsetinfo);
459     if(FAILED(hr)) return hr;
460 
461     hr = IRowsetInfo_GetProperties(rowsetinfo, cPropertyIDSets, rgPropertyIDSets, pcPropertySets, prgPropertySets);
462     IRowsetInfo_Release(rowsetinfo);
463 
464     TRACE("returning %08x\n", hr);
465     return hr;
466 }
467 
468 static HRESULT WINAPI server_GetReferencedRowset(IWineRowServer* iface, DBORDINAL iOrdinal,
469                                                  REFIID riid, IUnknown **ppReferencedRowset)
470 {
471     server *This = impl_from_IWineRowServer(iface);
472     FIXME("(%p): stub\n", This);
473     return E_NOTIMPL;
474 }
475 
476 static HRESULT WINAPI server_GetSpecification(IWineRowServer* iface, REFIID riid,
477                                                IUnknown **ppSpecification)
478 {
479     server *This = impl_from_IWineRowServer(iface);
480     FIXME("(%p): stub\n", This);
481     return E_NOTIMPL;
482 }
483 
484 static HRESULT WINAPI server_AddRefAccessor(IWineRowServer* iface, HACCESSOR hAccessor,
485                                             DBREFCOUNT *pcRefCount)
486 {
487     server *This = impl_from_IWineRowServer(iface);
488     FIXME("(%p): stub\n", This);
489     return E_NOTIMPL;
490 }
491 
492 static HRESULT WINAPI server_CreateAccessor(IWineRowServer* iface, DBACCESSORFLAGS dwAccessorFlags,
493                                             DBCOUNTITEM cBindings, const DBBINDING *rgBindings, DBLENGTH cbRowSize,
494                                             HACCESSOR *phAccessor, DBBINDSTATUS *rgStatus)
495 {
496     server *This = impl_from_IWineRowServer(iface);
497     HRESULT hr;
498     IAccessor *accessor;
499 
500     TRACE("(%p)->(%08x, %ld, %p, %ld, %p, %p)\n", This, dwAccessorFlags, cBindings, rgBindings, cbRowSize, phAccessor, rgStatus);
501 
502     hr = IUnknown_QueryInterface(This->inner_unk, &IID_IAccessor, (void**)&accessor);
503     if(FAILED(hr)) return hr;
504 
505     hr = IAccessor_CreateAccessor(accessor, dwAccessorFlags, cBindings, rgBindings, cbRowSize, phAccessor, rgStatus);
506     IAccessor_Release(accessor);
507 
508     TRACE("returning %08x, accessor %08lx\n", hr, *phAccessor);
509     return hr;
510 }
511 
512 static HRESULT WINAPI server_GetBindings(IWineRowServer* iface, HACCESSOR hAccessor,
513                                          DBACCESSORFLAGS *pdwAccessorFlags, DBCOUNTITEM *pcBindings,
514                                          DBBINDING **prgBindings)
515 {
516     server *This = impl_from_IWineRowServer(iface);
517     HRESULT hr;
518     IAccessor *accessor;
519 
520     TRACE("(%p)->(%08lx, %p, %p, %p)\n", This, hAccessor, pdwAccessorFlags, pcBindings, prgBindings);
521 
522     hr = IUnknown_QueryInterface(This->inner_unk, &IID_IAccessor, (void**)&accessor);
523     if(FAILED(hr)) return hr;
524 
525     hr = IAccessor_GetBindings(accessor, hAccessor, pdwAccessorFlags, pcBindings, prgBindings);
526     IAccessor_Release(accessor);
527 
528     TRACE("returning %08x\n", hr);
529     return hr;
530 }
531 
532 static HRESULT WINAPI server_ReleaseAccessor(IWineRowServer* iface, HACCESSOR hAccessor,
533                                              DBREFCOUNT *pcRefCount)
534 {
535     server *This = impl_from_IWineRowServer(iface);
536     HRESULT hr;
537     IAccessor *accessor;
538 
539     TRACE("(%p)->(%08lx, %p)\n", This, hAccessor, pcRefCount);
540 
541     hr = IUnknown_QueryInterface(This->inner_unk, &IID_IAccessor, (void**)&accessor);
542     if(FAILED(hr)) return hr;
543 
544     hr = IAccessor_ReleaseAccessor(accessor, hAccessor, pcRefCount);
545     IAccessor_Release(accessor);
546 
547     return hr;
548 }
549 
550 static const IWineRowServerVtbl server_vtbl =
551 {
552     server_QueryInterface,
553     server_AddRef,
554     server_Release,
555     server_SetInnerUnk,
556     server_GetMarshal,
557     server_GetColumns,
558     server_GetSourceRowset,
559     server_Open,
560     server_SetColumns,
561     server_AddRefRows,
562     server_GetData,
563     server_GetNextRows,
564     server_ReleaseRows,
565     server_RestartPosition,
566     server_Compare,
567     server_GetRowsAt,
568     server_GetRowsByBookmark,
569     server_Hash,
570     server_GetProperties,
571     server_GetReferencedRowset,
572     server_GetSpecification,
573     server_AddRefAccessor,
574     server_CreateAccessor,
575     server_GetBindings,
576     server_ReleaseAccessor
577 };
578 
579 static HRESULT create_server(IUnknown *outer, const CLSID *class, void **obj)
580 {
581     server *server;
582     TRACE("(%p, %s, %p)\n", outer, debugstr_guid(class), obj);
583 
584     *obj = NULL;
585 
586     server = HeapAlloc(GetProcessHeap(), 0, sizeof(*server));
587     if(!server) return E_OUTOFMEMORY;
588 
589     server->IWineRowServer_iface.lpVtbl = &server_vtbl;
590     server->ref = 1;
591     server->class = *class;
592     server->inner_unk = NULL;
593     if(IsEqualGUID(class, &CLSID_wine_row_server))
594         create_row_marshal((IUnknown*)server, (void**)&server->marshal);
595     else if(IsEqualGUID(class, &CLSID_wine_rowset_server))
596         create_rowset_marshal((IUnknown*)server, (void**)&server->marshal);
597     else
598         ERR("create_server called with class %s\n", debugstr_guid(class));
599 
600     *obj = server;
601     return S_OK;
602 }
603 
604 HRESULT create_row_server(IUnknown *outer, void **obj)
605 {
606     return create_server(outer, &CLSID_wine_row_server, obj);
607 }
608 
609 HRESULT create_rowset_server(IUnknown *outer, void **obj)
610 {
611     return create_server(outer, &CLSID_wine_rowset_server, obj);
612 }
613 
614 typedef struct
615 {
616     IRow IRow_iface;
617     IRowChange IRowChange_iface;
618 
619     LONG ref;
620 
621     IWineRowServer *server;
622 } row_proxy;
623 
624 static inline row_proxy *impl_from_IRow(IRow *iface)
625 {
626     return CONTAINING_RECORD(iface, row_proxy, IRow_iface);
627 }
628 
629 static inline row_proxy *impl_from_IRowChange(IRowChange *iface)
630 {
631     return CONTAINING_RECORD(iface, row_proxy, IRowChange_iface);
632 }
633 
634 static HRESULT WINAPI row_QueryInterface(IRow *iface, REFIID iid, void **obj)
635 {
636     row_proxy *This = impl_from_IRow(iface);
637     TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(iid), obj);
638 
639     if(IsEqualIID(iid, &IID_IUnknown) ||
640        IsEqualIID(iid, &IID_IRow))
641     {
642         *obj = &This->IRow_iface;
643     }
644     else if(IsEqualIID(iid, &IID_IRowChange))
645     {
646         *obj = &This->IRowChange_iface;
647     }
648     else
649     {
650         FIXME("interface %s not implemented\n", debugstr_guid(iid));
651         return E_NOINTERFACE;
652     }
653 
654     IRow_AddRef(iface);
655     return S_OK;
656 }
657 
658 static ULONG WINAPI row_AddRef(IRow *iface)
659 {
660     row_proxy *This = impl_from_IRow(iface);
661     TRACE("(%p)\n", This);
662 
663     return InterlockedIncrement(&This->ref);
664 }
665 
666 static ULONG WINAPI row_Release(IRow *iface)
667 {
668     row_proxy *This = impl_from_IRow(iface);
669     LONG ref;
670 
671     TRACE("(%p)\n", This);
672 
673     ref = InterlockedDecrement(&This->ref);
674     if(ref == 0)
675     {
676         if(This->server) IWineRowServer_Release(This->server);
677         HeapFree(GetProcessHeap(), 0, This);
678     }
679 
680     return ref;
681 }
682 
683 static HRESULT WINAPI row_GetColumns(IRow* iface, DBORDINAL cColumns, DBCOLUMNACCESS rgColumns[])
684 {
685     row_proxy *This = impl_from_IRow(iface);
686     DBORDINAL i;
687     wine_getcolumns_in *in_data;
688     wine_getcolumns_out *out_data;
689     HRESULT hr;
690 
691     TRACE("(%p)->(%ld, %p)\n", This, cColumns, rgColumns);
692 
693     in_data = CoTaskMemAlloc(cColumns * sizeof(in_data[0]));
694     out_data = CoTaskMemAlloc(cColumns * sizeof(out_data[0]));
695 
696     for(i = 0; i < cColumns; i++)
697     {
698         TRACE("%ld:\tdata %p data_len %ld status %08x max_len %ld type %04x\n", i, rgColumns[i].pData,
699               rgColumns[i].cbDataLen, rgColumns[i].dwStatus, rgColumns[i].cbMaxLen, rgColumns[i].wType);
700         in_data[i].columnid     = rgColumns[i].columnid;
701         in_data[i].max_len      = rgColumns[i].cbMaxLen;
702         in_data[i].type         = rgColumns[i].wType;
703         in_data[i].precision    = rgColumns[i].bPrecision;
704         in_data[i].scale        = rgColumns[i].bScale;
705     }
706 
707     hr = IWineRowServer_GetColumns(This->server, cColumns, in_data, out_data);
708 
709     for(i = 0; i < cColumns; i++)
710     {
711         rgColumns[i].cbDataLen = out_data[i].data_len;
712         rgColumns[i].dwStatus  = out_data[i].status;
713         if(rgColumns[i].dwStatus == DBSTATUS_S_OK)
714             memcpy(rgColumns[i].pData, &V_I1(&out_data[i].v), out_data[i].data_len);
715     }
716 
717     CoTaskMemFree(out_data);
718     CoTaskMemFree(in_data);
719     return hr;
720 }
721 
722 static HRESULT WINAPI row_GetSourceRowset(IRow* iface, REFIID riid, IUnknown **ppRowset,
723                                           HROW *phRow)
724 {
725     row_proxy *This = impl_from_IRow(iface);
726 
727     FIXME("(%p)->(%s, %p, %p): stub\n", This, debugstr_guid(riid), ppRowset, phRow);
728 
729     return E_NOTIMPL;
730 }
731 
732 static HRESULT WINAPI row_Open(IRow* iface, IUnknown *pUnkOuter,
733                                DBID *pColumnID, REFGUID rguidColumnType,
734                                DWORD dwBindFlags, REFIID riid, IUnknown **ppUnk)
735 {
736     row_proxy *This = impl_from_IRow(iface);
737 
738     TRACE("(%p)->(%p, %p, %s, %08x, %s, %p)\n", This, pUnkOuter, pColumnID, debugstr_guid(rguidColumnType),
739           dwBindFlags, debugstr_guid(riid), ppUnk);
740     if(pUnkOuter)
741     {
742         FIXME("Aggregation not supported\n");
743         return CLASS_E_NOAGGREGATION;
744     }
745 
746     return IWineRowServer_Open(This->server, pUnkOuter, pColumnID, rguidColumnType, dwBindFlags, riid, ppUnk);
747 }
748 
749 static const IRowVtbl row_vtbl =
750 {
751     row_QueryInterface,
752     row_AddRef,
753     row_Release,
754     row_GetColumns,
755     row_GetSourceRowset,
756     row_Open
757 };
758 
759 static HRESULT WINAPI row_change_QueryInterface(IRowChange *iface, REFIID iid, void **obj)
760 {
761     row_proxy *This = impl_from_IRowChange(iface);
762     return IUnknown_QueryInterface((IUnknown *)This, iid, obj);
763 }
764 
765 static ULONG WINAPI row_change_AddRef(IRowChange *iface)
766 {
767     row_proxy *This = impl_from_IRowChange(iface);
768     return IUnknown_AddRef((IUnknown*)This);
769 }
770 
771 static ULONG WINAPI row_change_Release(IRowChange *iface)
772 {
773     row_proxy *This = impl_from_IRowChange(iface);
774     return IUnknown_Release((IUnknown*)This);
775 }
776 
777 static HRESULT WINAPI row_change_SetColumns(IRowChange *iface, DBORDINAL cColumns,
778                                             DBCOLUMNACCESS rgColumns[])
779 {
780     row_proxy *This = impl_from_IRowChange(iface);
781     HRESULT hr;
782     wine_setcolumns_in *in_data;
783     DBSTATUS *status;
784     DBORDINAL i;
785 
786     TRACE("(%p)->(%ld, %p)\n", This, cColumns, rgColumns);
787 
788     in_data = CoTaskMemAlloc(cColumns * sizeof(in_data[0]));
789     status = CoTaskMemAlloc(cColumns * sizeof(status[0]));
790 
791     for(i = 0; i < cColumns; i++)
792     {
793         TRACE("%ld: wtype %04x max %08lx len %08lx\n", i, rgColumns[i].wType, rgColumns[i].cbMaxLen, rgColumns[i].cbDataLen);
794         V_VT(&in_data[i].v) = rgColumns[i].wType;
795         memcpy(&V_I1(&in_data[i].v), rgColumns[i].pData, db_type_size(rgColumns[i].wType, rgColumns[i].cbDataLen));
796         in_data[i].columnid = rgColumns[i].columnid;
797         in_data[i].data_len = rgColumns[i].cbDataLen;
798         in_data[i].status = rgColumns[i].dwStatus;
799         in_data[i].max_len = rgColumns[i].cbMaxLen;
800         in_data[i].type = rgColumns[i].wType;
801         in_data[i].precision = rgColumns[i].bPrecision;
802         in_data[i].scale = rgColumns[i].bScale;
803     }
804 
805     hr = IWineRowServer_SetColumns(This->server, cColumns, in_data, status);
806 
807     for(i = 0; i < cColumns; i++)
808         rgColumns[i].dwStatus = status[i];
809 
810     CoTaskMemFree(status);
811     CoTaskMemFree(in_data);
812 
813     return hr;
814 }
815 
816 static const IRowChangeVtbl row_change_vtbl =
817 {
818     row_change_QueryInterface,
819     row_change_AddRef,
820     row_change_Release,
821     row_change_SetColumns
822 };
823 
824 static HRESULT create_row_proxy(IWineRowServer *server, IUnknown **obj)
825 {
826     row_proxy *proxy;
827 
828     TRACE("(%p, %p)\n", server, obj);
829     *obj = NULL;
830 
831     proxy = HeapAlloc(GetProcessHeap(), 0, sizeof(*proxy));
832     if(!proxy) return E_OUTOFMEMORY;
833 
834     proxy->IRow_iface.lpVtbl = &row_vtbl;
835     proxy->IRowChange_iface.lpVtbl = &row_change_vtbl;
836     proxy->ref = 1;
837     IWineRowServer_AddRef(server);
838     proxy->server = server;
839 
840     *obj = (IUnknown*)&proxy->IRow_iface;
841     TRACE("returning %p\n", *obj);
842     return S_OK;
843 }
844 
845 typedef struct
846 {
847     IRowsetLocate IRowsetLocate_iface;
848     IRowsetInfo IRowsetInfo_iface;
849     IAccessor IAccessor_iface;
850 
851     LONG ref;
852 
853     IWineRowServer *server;
854 } rowset_proxy;
855 
856 static inline rowset_proxy *impl_from_IRowsetLocate(IRowsetLocate *iface)
857 {
858     return CONTAINING_RECORD(iface, rowset_proxy, IRowsetLocate_iface);
859 }
860 
861 static inline rowset_proxy *impl_from_IRowsetInfo(IRowsetInfo *iface)
862 {
863     return CONTAINING_RECORD(iface, rowset_proxy, IRowsetInfo_iface);
864 }
865 
866 static inline rowset_proxy *impl_from_IAccessor(IAccessor *iface)
867 {
868     return CONTAINING_RECORD(iface, rowset_proxy, IAccessor_iface);
869 }
870 
871 static HRESULT WINAPI rowsetlocate_QueryInterface(IRowsetLocate *iface, REFIID iid, void **obj)
872 {
873     rowset_proxy *This = impl_from_IRowsetLocate(iface);
874     TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(iid), obj);
875 
876     *obj = NULL;
877 
878     if(IsEqualIID(iid, &IID_IUnknown) ||
879        IsEqualIID(iid, &IID_IRowset) ||
880        IsEqualIID(iid, &IID_IRowsetLocate))
881     {
882         *obj = &This->IRowsetLocate_iface;
883     }
884     else if(IsEqualIID(iid, &IID_IRowsetInfo))
885     {
886         *obj = &This->IRowsetInfo_iface;
887     }
888     else if(IsEqualIID(iid, &IID_IAccessor))
889     {
890         *obj = &This->IAccessor_iface;
891     }
892     else
893     {
894         FIXME("interface %s not implemented\n", debugstr_guid(iid));
895         return E_NOINTERFACE;
896     }
897 
898     IRowset_AddRef(iface);
899     return S_OK;
900 }
901 
902 static ULONG WINAPI rowsetlocate_AddRef(IRowsetLocate *iface)
903 {
904     rowset_proxy *This = impl_from_IRowsetLocate(iface);
905     TRACE("(%p)\n", This);
906 
907     return InterlockedIncrement(&This->ref);
908 }
909 
910 static ULONG WINAPI rowsetlocate_Release(IRowsetLocate *iface)
911 {
912     rowset_proxy *This = impl_from_IRowsetLocate(iface);
913     LONG ref;
914 
915     TRACE("(%p)\n", This);
916 
917     ref = InterlockedDecrement(&This->ref);
918     if(ref == 0)
919     {
920         if(This->server) IWineRowServer_Release(This->server);
921         HeapFree(GetProcessHeap(), 0, This);
922     }
923 
924     return ref;
925 }
926 
927 static HRESULT WINAPI rowsetlocate_AddRefRows(IRowsetLocate *iface, DBCOUNTITEM cRows, const HROW rghRows[],
928                                               DBREFCOUNT rgRefCounts[], DBROWSTATUS rgRowStatus[])
929 {
930     rowset_proxy *This = impl_from_IRowsetLocate(iface);
931     HRESULT hr;
932     DBREFCOUNT *refs = rgRefCounts;
933     DBSTATUS *stats = rgRowStatus;
934 
935     TRACE("(%p)->(%ld, %p, %p, %p)\n", This, cRows, rghRows, rgRefCounts, rgRowStatus);
936 
937     if(!refs) refs = CoTaskMemAlloc(cRows * sizeof(refs[0]));
938     if(!stats) stats = CoTaskMemAlloc(cRows * sizeof(stats[0]));
939 
940     hr = IWineRowServer_AddRefRows(This->server, cRows, rghRows, refs, stats);
941 
942     if(refs != rgRefCounts) CoTaskMemFree(refs);
943     if(stats != rgRowStatus) CoTaskMemFree(stats);
944 
945     return hr;
946 }
947 
948 static HRESULT WINAPI rowsetlocate_GetData(IRowsetLocate *iface, HROW hRow, HACCESSOR hAccessor, void *pData)
949 {
950     rowset_proxy *This = impl_from_IRowsetLocate(iface);
951     HRESULT hr;
952     IAccessor *accessor;
953     DBACCESSORFLAGS flags;
954     DBCOUNTITEM count, i;
955     DBBINDING *bindings;
956     DWORD max_len = 0;
957 
958     TRACE("(%p)->(%lx, %lx, %p)\n", This, hRow, hAccessor, pData);
959 
960     hr = IRowsetLocate_QueryInterface(iface, &IID_IAccessor, (void**)&accessor);
961     if(FAILED(hr)) return hr;
962 
963     hr = IAccessor_GetBindings(accessor, hAccessor, &flags, &count, &bindings);
964     IAccessor_Release(accessor);
965     if(FAILED(hr)) return hr;
966 
967     TRACE("got %ld bindings\n", count);
968     for(i = 0; i < count; i++)
969     {
970         TRACE("%ld\tord %ld offs: val %ld len %ld stat %ld, part %x, max len %ld type %04x\n",
971               i, bindings[i].iOrdinal, bindings[i].obValue, bindings[i].obLength, bindings[i].obStatus,
972               bindings[i].dwPart, bindings[i].cbMaxLen, bindings[i].wType);
973         if(bindings[i].dwPart & DBPART_LENGTH && bindings[i].obLength >= max_len)
974             max_len = bindings[i].obLength + sizeof(DBLENGTH);
975         if(bindings[i].dwPart & DBPART_STATUS && bindings[i].obStatus >= max_len)
976             max_len = bindings[i].obStatus + sizeof(DWORD);
977         if(bindings[i].dwPart & DBPART_VALUE && bindings[i].obValue >= max_len)
978             max_len = bindings[i].obValue + db_type_size(bindings[i].wType, bindings[i].cbMaxLen);
979 
980     }
981     TRACE("max_len %d\n", max_len);
982 
983     CoTaskMemFree(bindings);
984 
985     hr = IWineRowServer_GetData(This->server, hRow, hAccessor, pData, max_len);
986 
987     return hr;
988 }
989 
990 static HRESULT WINAPI rowsetlocate_GetNextRows(IRowsetLocate *iface, HCHAPTER hReserved, DBROWOFFSET lRowsOffset,
991                                                DBROWCOUNT cRows, DBCOUNTITEM *pcRowObtained, HROW **prghRows)
992 {
993     rowset_proxy *This = impl_from_IRowsetLocate(iface);
994     HRESULT hr;
995     HROW *rows = NULL;
996 
997     TRACE("(%p)->(%08lx, %ld, %ld, %p, %p)\n", This, hReserved, lRowsOffset, cRows, pcRowObtained, prghRows);
998 
999     hr = IWineRowServer_GetNextRows(This->server, hReserved, lRowsOffset, cRows, pcRowObtained, &rows);
1000     if(*prghRows)
1001     {
1002         memcpy(*prghRows, rows, *pcRowObtained * sizeof(rows[0]));
1003         CoTaskMemFree(rows);
1004     }
1005     else
1006         *prghRows = rows;
1007 
1008     return hr;
1009 }
1010 
1011 static HRESULT WINAPI rowsetlocate_ReleaseRows(IRowsetLocate *iface, DBCOUNTITEM cRows, const HROW rghRows[],
1012                                                DBROWOPTIONS rgRowOptions[], DBREFCOUNT rgRefCounts[], DBROWSTATUS rgRowStatus[])
1013 {
1014     rowset_proxy *This = impl_from_IRowsetLocate(iface);
1015     HRESULT hr;
1016     DBROWOPTIONS *options = rgRowOptions;
1017     DBREFCOUNT *refs = rgRefCounts;
1018     DBROWSTATUS *status = rgRowStatus;
1019 
1020     TRACE("(%p)->(%ld, %p, %p, %p, %p)\n", This, cRows, rghRows, rgRowOptions, rgRefCounts, rgRowStatus);
1021 
1022     if(!options)
1023     {
1024         options = CoTaskMemAlloc(cRows * sizeof(options[0]));
1025         memset(options, 0, cRows * sizeof(options[0]));
1026     }
1027     if(!refs) refs = CoTaskMemAlloc(cRows * sizeof(refs[0]));
1028     if(!status) status = CoTaskMemAlloc(cRows * sizeof(status[0]));
1029 
1030     hr = IWineRowServer_ReleaseRows(This->server, cRows, rghRows, options, refs, status);
1031 
1032     if(status != rgRowStatus) CoTaskMemFree(status);
1033     if(refs != rgRefCounts) CoTaskMemFree(refs);
1034     if(options != rgRowOptions) CoTaskMemFree(options);
1035 
1036     return hr;
1037 }
1038 
1039 static HRESULT WINAPI rowsetlocate_RestartPosition(IRowsetLocate* iface, HCHAPTER hReserved)
1040 {
1041     rowset_proxy *This = impl_from_IRowsetLocate(iface);
1042 
1043     FIXME("(%p)->(%lx): stub\n", This, hReserved);
1044 
1045     return E_NOTIMPL;
1046 }
1047 
1048 static HRESULT WINAPI rowsetlocate_Compare(IRowsetLocate *iface, HCHAPTER hReserved, DBBKMARK cbBookmark1, const BYTE *pBookmark1,
1049                                            DBBKMARK cbBookmark2, const BYTE *pBookmark2, DBCOMPARE *pComparison)
1050 {
1051     rowset_proxy *This = impl_from_IRowsetLocate(iface);
1052     FIXME("(%p)\n", This);
1053     return E_NOTIMPL;
1054 }
1055 
1056 static HRESULT WINAPI rowsetlocate_GetRowsAt(IRowsetLocate *iface, HWATCHREGION hReserved1, HCHAPTER hReserved2, DBBKMARK cbBookmark,
1057                                              const BYTE *pBookmark, DBROWOFFSET lRowsOffset, DBROWCOUNT cRows, DBCOUNTITEM *pcRowsObtained,
1058                                              HROW **prghRows)
1059 {
1060     rowset_proxy *This = impl_from_IRowsetLocate(iface);
1061     HRESULT hr;
1062     HROW *rows = NULL;
1063 
1064     TRACE("(%p)->(%08lx, %08lx, %ld, %p, %ld, %ld, %p, %p\n", This, hReserved1, hReserved2, cbBookmark, pBookmark, lRowsOffset, cRows,
1065           pcRowsObtained, prghRows);
1066 
1067     hr = IWineRowServer_GetRowsAt(This->server, hReserved1, hReserved2, cbBookmark, pBookmark, lRowsOffset, cRows, pcRowsObtained, &rows);
1068 
1069     if(*prghRows)
1070     {
1071         memcpy(*prghRows, rows, *pcRowsObtained * sizeof(rows[0]));
1072         CoTaskMemFree(rows);
1073     }
1074     else
1075         *prghRows = rows;
1076 
1077     return hr;
1078 }
1079 
1080 static HRESULT WINAPI rowsetlocate_GetRowsByBookmark(IRowsetLocate *iface, HCHAPTER hReserved, DBCOUNTITEM cRows, const DBBKMARK rgcbBookmarks[],
1081                                                      const BYTE * rgpBookmarks[], HROW rghRows[], DBROWSTATUS rgRowStatus[])
1082 {
1083     rowset_proxy *This = impl_from_IRowsetLocate(iface);
1084     FIXME("(%p)\n", This);
1085     return E_NOTIMPL;
1086 }
1087 
1088 static HRESULT WINAPI rowsetlocate_Hash(IRowsetLocate *iface, HCHAPTER hReserved, DBBKMARK cBookmarks, const DBBKMARK rgcbBookmarks[],
1089                                         const BYTE * rgpBookmarks[], DBHASHVALUE rgHashedValues[], DBROWSTATUS rgBookmarkStatus[])
1090 {
1091     rowset_proxy *This = impl_from_IRowsetLocate(iface);
1092     FIXME("(%p)\n", This);
1093     return E_NOTIMPL;
1094 }
1095 
1096 static const IRowsetLocateVtbl rowsetlocate_vtbl =
1097 {
1098     rowsetlocate_QueryInterface,
1099     rowsetlocate_AddRef,
1100     rowsetlocate_Release,
1101     rowsetlocate_AddRefRows,
1102     rowsetlocate_GetData,
1103     rowsetlocate_GetNextRows,
1104     rowsetlocate_ReleaseRows,
1105     rowsetlocate_RestartPosition,
1106     rowsetlocate_Compare,
1107     rowsetlocate_GetRowsAt,
1108     rowsetlocate_GetRowsByBookmark,
1109     rowsetlocate_Hash
1110 };
1111 
1112 static HRESULT WINAPI rowsetinfo_QueryInterface(IRowsetInfo *iface, REFIID iid, void **obj)
1113 {
1114     rowset_proxy *This = impl_from_IRowsetInfo(iface);
1115     return IUnknown_QueryInterface((IUnknown *)This, iid, obj);
1116 }
1117 
1118 static ULONG WINAPI rowsetinfo_AddRef(IRowsetInfo *iface)
1119 {
1120     rowset_proxy *This = impl_from_IRowsetInfo(iface);
1121     return IUnknown_AddRef((IUnknown *)This);
1122 }
1123 
1124 static ULONG WINAPI rowsetinfo_Release(IRowsetInfo *iface)
1125 {
1126     rowset_proxy *This = impl_from_IRowsetInfo(iface);
1127     return IUnknown_Release((IUnknown *)This);
1128 }
1129 
1130 static HRESULT WINAPI rowsetinfo_GetProperties(IRowsetInfo *iface, const ULONG cPropertyIDSets,
1131                                                const DBPROPIDSET rgPropertyIDSets[], ULONG *pcPropertySets,
1132                                                DBPROPSET **prgPropertySets)
1133 {
1134     rowset_proxy *This = impl_from_IRowsetInfo(iface);
1135     HRESULT hr;
1136 
1137     TRACE("(%p)->(%d, %p, %p, %p)\n", This, cPropertyIDSets, rgPropertyIDSets, pcPropertySets, prgPropertySets);
1138 
1139     hr = IWineRowServer_GetProperties(This->server, cPropertyIDSets, rgPropertyIDSets, pcPropertySets, prgPropertySets);
1140 
1141     return hr;
1142 }
1143 
1144 static HRESULT WINAPI rowsetinfo_GetReferencedRowset(IRowsetInfo *iface, DBORDINAL iOrdinal, REFIID riid,
1145                                                      IUnknown **ppReferencedRowset)
1146 {
1147     rowset_proxy *This = impl_from_IRowsetInfo(iface);
1148     FIXME("(%p)\n", This);
1149     return E_NOTIMPL;
1150 }
1151 
1152 static HRESULT WINAPI rowsetinfo_GetSpecification(IRowsetInfo *iface, REFIID riid, IUnknown **ppSpecification)
1153 {
1154     rowset_proxy *This = impl_from_IRowsetInfo(iface);
1155     FIXME("(%p)\n", This);
1156     return E_NOTIMPL;
1157 }
1158 
1159 static const IRowsetInfoVtbl rowsetinfo_vtbl =
1160 {
1161     rowsetinfo_QueryInterface,
1162     rowsetinfo_AddRef,
1163     rowsetinfo_Release,
1164     rowsetinfo_GetProperties,
1165     rowsetinfo_GetReferencedRowset,
1166     rowsetinfo_GetSpecification
1167 };
1168 
1169 static HRESULT WINAPI accessor_QueryInterface(IAccessor *iface, REFIID iid, void **obj)
1170 {
1171     rowset_proxy *This = impl_from_IAccessor(iface);
1172     return IUnknown_QueryInterface((IUnknown *)This, iid, obj);
1173 }
1174 
1175 static ULONG WINAPI accessor_AddRef(IAccessor *iface)
1176 {
1177     rowset_proxy *This = impl_from_IAccessor(iface);
1178     return IUnknown_AddRef((IUnknown *)This);
1179 }
1180 
1181 static ULONG WINAPI accessor_Release(IAccessor *iface)
1182 {
1183     rowset_proxy *This = impl_from_IAccessor(iface);
1184     return IUnknown_Release((IUnknown *)This);
1185 }
1186 
1187 static HRESULT WINAPI accessor_AddRefAccessor(IAccessor *iface, HACCESSOR hAccessor, DBREFCOUNT *pcRefCount)
1188 {
1189     rowset_proxy *This = impl_from_IAccessor(iface);
1190     FIXME("(%p)\n", This);
1191     return E_NOTIMPL;
1192 }
1193 
1194 static HRESULT WINAPI accessor_CreateAccessor(IAccessor *iface, DBACCESSORFLAGS dwAccessorFlags, DBCOUNTITEM cBindings,
1195                                               const DBBINDING rgBindings[], DBLENGTH cbRowSize, HACCESSOR *phAccessor,
1196                                               DBBINDSTATUS rgStatus[])
1197 {
1198     rowset_proxy *This = impl_from_IAccessor(iface);
1199     HRESULT hr;
1200     DBBINDSTATUS *status;
1201 
1202     TRACE("(%p)->(%08x, %ld, %p, %ld, %p, %p)\n", This, dwAccessorFlags, cBindings, rgBindings, cbRowSize, phAccessor, rgStatus);
1203 
1204     if(!rgStatus) status = CoTaskMemAlloc(cBindings * sizeof(status[0]));
1205     else status = rgStatus;
1206 
1207     hr = IWineRowServer_CreateAccessor(This->server, dwAccessorFlags, cBindings, rgBindings, cbRowSize, phAccessor, status);
1208 
1209     if(!rgStatus) CoTaskMemFree(status);
1210 
1211     return hr;
1212 }
1213 
1214 static HRESULT WINAPI accessor_GetBindings(IAccessor *iface, HACCESSOR hAccessor, DBACCESSORFLAGS *pdwAccessorFlags,
1215                                            DBCOUNTITEM *pcBindings, DBBINDING **prgBindings)
1216 {
1217     rowset_proxy *This = impl_from_IAccessor(iface);
1218     HRESULT hr;
1219 
1220     TRACE("(%p)->(%08lx, %p, %p, %p)\n", This, hAccessor, pdwAccessorFlags, pcBindings, prgBindings);
1221 
1222     hr = IWineRowServer_GetBindings(This->server, hAccessor, pdwAccessorFlags, pcBindings, prgBindings);
1223 
1224     return hr;
1225 }
1226 
1227 static HRESULT WINAPI accessor_ReleaseAccessor(IAccessor *iface, HACCESSOR hAccessor, DBREFCOUNT *pcRefCount)
1228 {
1229     rowset_proxy *This = impl_from_IAccessor(iface);
1230     HRESULT hr;
1231     DBREFCOUNT ref;
1232 
1233     TRACE("(%p)->(%08lx, %p)\n", This, hAccessor, pcRefCount);
1234 
1235     hr = IWineRowServer_ReleaseAccessor(This->server, hAccessor, &ref);
1236     if(pcRefCount) *pcRefCount = ref;
1237     return hr;
1238 }
1239 
1240 static const IAccessorVtbl accessor_vtbl =
1241 {
1242     accessor_QueryInterface,
1243     accessor_AddRef,
1244     accessor_Release,
1245     accessor_AddRefAccessor,
1246     accessor_CreateAccessor,
1247     accessor_GetBindings,
1248     accessor_ReleaseAccessor
1249 };
1250 
1251 static HRESULT create_rowset_proxy(IWineRowServer *server, IUnknown **obj)
1252 {
1253     rowset_proxy *proxy;
1254 
1255     TRACE("(%p, %p)\n", server, obj);
1256     *obj = NULL;
1257 
1258     proxy = HeapAlloc(GetProcessHeap(), 0, sizeof(*proxy));
1259     if(!proxy) return E_OUTOFMEMORY;
1260 
1261     proxy->IRowsetLocate_iface.lpVtbl = &rowsetlocate_vtbl;
1262     proxy->IRowsetInfo_iface.lpVtbl = &rowsetinfo_vtbl;
1263     proxy->IAccessor_iface.lpVtbl = &accessor_vtbl;
1264     proxy->ref = 1;
1265     IWineRowServer_AddRef(server);
1266     proxy->server = server;
1267 
1268     *obj = (IUnknown *)&proxy->IRowsetLocate_iface;
1269     TRACE("returning %p\n", *obj);
1270     return S_OK;
1271 }
1272 
1273 static HRESULT create_proxy(IWineRowServer *server, const CLSID *class, IUnknown **obj)
1274 {
1275     *obj = NULL;
1276 
1277     if(IsEqualGUID(class, &CLSID_wine_row_proxy))
1278         return create_row_proxy(server, obj);
1279     else if(IsEqualGUID(class, &CLSID_wine_rowset_proxy))
1280         return create_rowset_proxy(server, obj);
1281     else
1282         FIXME("Unhandled proxy class %s\n", debugstr_guid(class));
1283     return E_NOTIMPL;
1284 }
1285 
1286 /* Marshal impl */
1287 
1288 typedef struct
1289 {
1290     IMarshal IMarshal_iface;
1291 
1292     LONG ref;
1293     CLSID unmarshal_class;
1294     IUnknown *outer;
1295 } marshal;
1296 
1297 static inline marshal *impl_from_IMarshal(IMarshal *iface)
1298 {
1299     return CONTAINING_RECORD(iface, marshal, IMarshal_iface);
1300 }
1301 
1302 static HRESULT WINAPI marshal_QueryInterface(IMarshal *iface, REFIID iid, void **obj)
1303 {
1304     marshal *This = impl_from_IMarshal(iface);
1305     TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(iid), obj);
1306 
1307     if(IsEqualIID(iid, &IID_IUnknown) ||
1308        IsEqualIID(iid, &IID_IMarshal))
1309     {
1310         *obj = iface;
1311     }
1312     else
1313     {
1314         FIXME("interface %s not implemented\n", debugstr_guid(iid));
1315         *obj = NULL;
1316         return E_NOINTERFACE;
1317     }
1318 
1319     IMarshal_AddRef(iface);
1320     return S_OK;
1321 }
1322 
1323 static ULONG WINAPI marshal_AddRef(IMarshal *iface)
1324 {
1325     marshal *This = impl_from_IMarshal(iface);
1326     TRACE("(%p)\n", This);
1327     return InterlockedIncrement(&This->ref);
1328 }
1329 
1330 static ULONG WINAPI marshal_Release(IMarshal *iface)
1331 {
1332     marshal *This = impl_from_IMarshal(iface);
1333     LONG ref;
1334 
1335     TRACE("(%p)\n", This);
1336 
1337     ref = InterlockedDecrement(&This->ref);
1338     if(ref == 0)
1339     {
1340         HeapFree(GetProcessHeap(), 0, This);
1341     }
1342 
1343     return ref;
1344 }
1345 
1346 static HRESULT WINAPI marshal_GetUnmarshalClass(IMarshal *iface, REFIID iid, void *obj,
1347                                                 DWORD dwDestContext, void *pvDestContext,
1348                                                 DWORD mshlflags, CLSID *clsid)
1349 {
1350     marshal *This = impl_from_IMarshal(iface);
1351     TRACE("(%p)->(%s, %p, %08x, %p, %08x, %p)\n", This, debugstr_guid(iid), obj, dwDestContext,
1352           pvDestContext, mshlflags, clsid);
1353 
1354     *clsid = This->unmarshal_class;
1355     return S_OK;
1356 }
1357 
1358 static HRESULT WINAPI marshal_GetMarshalSizeMax(IMarshal *iface, REFIID iid, void *obj,
1359                                                 DWORD dwDestContext, void *pvDestContext,
1360                                                 DWORD mshlflags, DWORD *size)
1361 {
1362     marshal *This = impl_from_IMarshal(iface);
1363     TRACE("(%p)->(%s, %p, %08x, %p, %08x, %p)\n", This, debugstr_guid(iid), obj, dwDestContext,
1364           pvDestContext, mshlflags, size);
1365 
1366     return CoGetMarshalSizeMax(size, &IID_IWineRowServer, This->outer, dwDestContext, pvDestContext,
1367                                mshlflags);
1368 }
1369 
1370 static HRESULT WINAPI marshal_MarshalInterface(IMarshal *iface, IStream *stream, REFIID iid,
1371                                                void *obj, DWORD dwDestContext, void *pvDestContext,
1372                                                DWORD mshlflags)
1373 {
1374     marshal *This = impl_from_IMarshal(iface);
1375     TRACE("(%p)->(%p, %s, %p, %08x, %p, %08x)\n", This, stream, debugstr_guid(iid), obj, dwDestContext,
1376           pvDestContext, mshlflags);
1377 
1378     return CoMarshalInterface(stream, &IID_IWineRowServer, This->outer, dwDestContext, pvDestContext, mshlflags);
1379 }
1380 
1381 static HRESULT WINAPI marshal_UnmarshalInterface(IMarshal *iface, IStream *stream,
1382                                                  REFIID iid, void **obj)
1383 {
1384     marshal *This = impl_from_IMarshal(iface);
1385     HRESULT hr;
1386     IWineRowServer *server;
1387     IUnknown *proxy;
1388 
1389     TRACE("(%p)->(%p, %s, %p)\n", This, stream, debugstr_guid(iid), obj);
1390     *obj = NULL;
1391 
1392     hr = CoUnmarshalInterface(stream, &IID_IWineRowServer, (void**)&server);
1393     if(SUCCEEDED(hr))
1394     {
1395         hr = create_proxy(server, &This->unmarshal_class, &proxy);
1396         if(SUCCEEDED(hr))
1397         {
1398             hr = IUnknown_QueryInterface(proxy, iid, obj);
1399             IUnknown_Release(proxy);
1400         }
1401         IWineRowServer_Release(server);
1402     }
1403 
1404     TRACE("returning %p\n", *obj);
1405     return hr;
1406 }
1407 
1408 static HRESULT WINAPI marshal_ReleaseMarshalData(IMarshal *iface, IStream *stream)
1409 {
1410     marshal *This = impl_from_IMarshal(iface);
1411     TRACE("(%p)->(%p)\n", This, stream);
1412     return CoReleaseMarshalData(stream);
1413 }
1414 
1415 static HRESULT WINAPI marshal_DisconnectObject(IMarshal *iface, DWORD dwReserved)
1416 {
1417     marshal *This = impl_from_IMarshal(iface);
1418     FIXME("(%p)->(%08x)\n", This, dwReserved);
1419 
1420     return E_NOTIMPL;
1421 }
1422 
1423 static const IMarshalVtbl marshal_vtbl =
1424 {
1425     marshal_QueryInterface,
1426     marshal_AddRef,
1427     marshal_Release,
1428     marshal_GetUnmarshalClass,
1429     marshal_GetMarshalSizeMax,
1430     marshal_MarshalInterface,
1431     marshal_UnmarshalInterface,
1432     marshal_ReleaseMarshalData,
1433     marshal_DisconnectObject
1434 };
1435 
1436 static HRESULT create_marshal(IUnknown *outer, const CLSID *class, void **obj)
1437 {
1438     marshal *marshal;
1439 
1440     TRACE("(%p, %p)\n", outer, obj);
1441     *obj = NULL;
1442 
1443     marshal = HeapAlloc(GetProcessHeap(), 0, sizeof(*marshal));
1444     if(!marshal) return E_OUTOFMEMORY;
1445 
1446     marshal->unmarshal_class = *class;
1447     marshal->outer = outer; /* don't ref outer unk */
1448     marshal->IMarshal_iface.lpVtbl = &marshal_vtbl;
1449     marshal->ref = 1;
1450 
1451     *obj = &marshal->IMarshal_iface;
1452     TRACE("returning %p\n", *obj);
1453     return S_OK;
1454 }
1455 
1456 HRESULT create_row_marshal(IUnknown *outer, void **obj)
1457 {
1458     TRACE("(%p, %p)\n", outer, obj);
1459     return create_marshal(outer, &CLSID_wine_row_proxy, obj);
1460 }
1461 
1462 HRESULT create_rowset_marshal(IUnknown *outer, void **obj)
1463 {
1464     TRACE("(%p, %p)\n", outer, obj);
1465     return create_marshal(outer, &CLSID_wine_rowset_proxy, obj);
1466 }
1467 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.