ntdll: Allow NtQueryVolumeInformationFile to make async volume information queries.
[wine/zf.git] / dlls / msado15 / recordset.c
blobe830f66e1ba782a76aae205ecf6f7ae17b3c27b2
1 /*
2 * Copyright 2019 Hans Leidekker for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <stdarg.h>
20 #include <assert.h>
21 #include "windef.h"
22 #include "winbase.h"
23 #define COBJMACROS
24 #include "objbase.h"
25 #include "msado15_backcompat.h"
26 #include "oledb.h"
28 #include "wine/debug.h"
29 #include "wine/heap.h"
31 #include "msado15_private.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(msado15);
35 struct fields;
36 struct recordset
38 _Recordset Recordset_iface;
39 ADORecordsetConstruction ADORecordsetConstruction_iface;
40 ISupportErrorInfo ISupportErrorInfo_iface;
41 LONG refs;
42 LONG state;
43 struct fields *fields;
44 LONG count;
45 LONG allocated;
46 LONG index;
47 VARIANT *data;
48 CursorLocationEnum cursor_location;
49 CursorTypeEnum cursor_type;
50 IRowset *row_set;
53 struct fields
55 Fields Fields_iface;
56 ISupportErrorInfo ISupportErrorInfo_iface;
57 LONG refs;
58 Field **field;
59 ULONG count;
60 ULONG allocated;
61 struct recordset *recordset;
64 struct field
66 Field Field_iface;
67 ISupportErrorInfo ISupportErrorInfo_iface;
68 LONG refs;
69 WCHAR *name;
70 DataTypeEnum type;
71 LONG defined_size;
72 LONG attrs;
73 LONG index;
74 struct recordset *recordset;
77 static inline struct field *impl_from_Field( Field *iface )
79 return CONTAINING_RECORD( iface, struct field, Field_iface );
82 static ULONG WINAPI field_AddRef( Field *iface )
84 struct field *field = impl_from_Field( iface );
85 LONG refs = InterlockedIncrement( &field->refs );
86 TRACE( "%p new refcount %d\n", field, refs );
87 return refs;
90 static ULONG WINAPI field_Release( Field *iface )
92 struct field *field = impl_from_Field( iface );
93 LONG refs = InterlockedDecrement( &field->refs );
94 TRACE( "%p new refcount %d\n", field, refs );
95 if (!refs)
97 TRACE( "destroying %p\n", field );
98 heap_free( field->name );
99 heap_free( field );
101 return refs;
104 static HRESULT WINAPI field_QueryInterface( Field *iface, REFIID riid, void **obj )
106 struct field *field = impl_from_Field( iface );
107 TRACE( "%p, %s, %p\n", iface, debugstr_guid(riid), obj );
109 if (IsEqualGUID( riid, &IID_Field ) || IsEqualGUID( riid, &IID_IDispatch ) ||
110 IsEqualGUID( riid, &IID_IUnknown ))
112 *obj = iface;
114 else if (IsEqualGUID( riid, &IID_ISupportErrorInfo ))
116 *obj = &field->ISupportErrorInfo_iface;
118 else
120 FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
121 return E_NOINTERFACE;
123 field_AddRef( iface );
124 return S_OK;
127 static HRESULT WINAPI field_GetTypeInfoCount( Field *iface, UINT *count )
129 FIXME( "%p, %p\n", iface, count );
130 return E_NOTIMPL;
133 static HRESULT WINAPI field_GetTypeInfo( Field *iface, UINT index, LCID lcid, ITypeInfo **info )
135 FIXME( "%p, %u, %u, %p\n", iface, index, lcid, info );
136 return E_NOTIMPL;
139 static HRESULT WINAPI field_GetIDsOfNames( Field *iface, REFIID riid, LPOLESTR *names, UINT count,
140 LCID lcid, DISPID *dispid )
142 FIXME( "%p, %s, %p, %u, %u, %p\n", iface, debugstr_guid(riid), names, count, lcid, dispid );
143 return E_NOTIMPL;
146 static HRESULT WINAPI field_Invoke( Field *iface, DISPID member, REFIID riid, LCID lcid, WORD flags,
147 DISPPARAMS *params, VARIANT *result, EXCEPINFO *excep_info, UINT *arg_err )
149 FIXME( "%p, %d, %s, %d, %d, %p, %p, %p, %p\n", iface, member, debugstr_guid(riid), lcid, flags, params,
150 result, excep_info, arg_err );
151 return E_NOTIMPL;
154 static HRESULT WINAPI field_get_Properties( Field *iface, Properties **obj )
156 FIXME( "%p, %p\n", iface, obj );
157 return E_NOTIMPL;
160 static HRESULT WINAPI field_get_ActualSize( Field *iface, LONG *size )
162 FIXME( "%p, %p\n", iface, size );
163 return E_NOTIMPL;
166 static HRESULT WINAPI field_get_Attributes( Field *iface, LONG *attrs )
168 struct field *field = impl_from_Field( iface );
170 TRACE( "%p, %p\n", field, attrs );
172 *attrs = field->attrs;
173 return S_OK;
176 static HRESULT WINAPI field_get_DefinedSize( Field *iface, LONG *size )
178 struct field *field = impl_from_Field( iface );
180 TRACE( "%p, %p\n", field, size );
182 *size = field->defined_size;
183 return S_OK;
186 static HRESULT WINAPI field_get_Name( Field *iface, BSTR *str )
188 struct field *field = impl_from_Field( iface );
189 BSTR name;
191 TRACE( "%p, %p\n", field, str );
193 if (!(name = SysAllocString( field->name ))) return E_OUTOFMEMORY;
194 *str = name;
195 return S_OK;
198 static HRESULT WINAPI field_get_Type( Field *iface, DataTypeEnum *type )
200 struct field *field = impl_from_Field( iface );
202 TRACE( "%p, %p\n", field, type );
204 *type = field->type;
205 return S_OK;
208 static LONG get_column_count( struct recordset *recordset )
210 return recordset->fields->count;
213 static HRESULT WINAPI field_get_Value( Field *iface, VARIANT *val )
215 struct field *field = impl_from_Field( iface );
216 ULONG row = field->recordset->index, col = field->index, col_count;
217 VARIANT copy;
218 HRESULT hr;
220 TRACE( "%p, %p\n", field, val );
222 if (field->recordset->state == adStateClosed) return MAKE_ADO_HRESULT( adErrObjectClosed );
223 if (field->recordset->index < 0) return MAKE_ADO_HRESULT( adErrNoCurrentRecord );
225 col_count = get_column_count( field->recordset );
227 VariantInit( &copy );
228 if ((hr = VariantCopy( &copy, &field->recordset->data[row * col_count + col] )) != S_OK) return hr;
230 *val = copy;
231 return S_OK;
234 static HRESULT WINAPI field_put_Value( Field *iface, VARIANT val )
236 struct field *field = impl_from_Field( iface );
237 ULONG row = field->recordset->index, col = field->index, col_count;
238 VARIANT copy;
239 HRESULT hr;
241 TRACE( "%p, %s\n", field, debugstr_variant(&val) );
243 if (field->recordset->state == adStateClosed) return MAKE_ADO_HRESULT( adErrObjectClosed );
244 if (field->recordset->index < 0) return MAKE_ADO_HRESULT( adErrNoCurrentRecord );
246 col_count = get_column_count( field->recordset );
248 VariantInit( &copy );
249 if ((hr = VariantCopy( &copy, &val )) != S_OK) return hr;
251 field->recordset->data[row * col_count + col] = copy;
252 return S_OK;
255 static HRESULT WINAPI field_get_Precision( Field *iface, unsigned char *precision )
257 FIXME( "%p, %p\n", iface, precision );
258 return E_NOTIMPL;
261 static HRESULT WINAPI field_get_NumericScale( Field *iface, unsigned char *scale )
263 FIXME( "%p, %p\n", iface, scale );
264 return E_NOTIMPL;
267 static HRESULT WINAPI field_AppendChunk( Field *iface, VARIANT data )
269 FIXME( "%p, %s\n", iface, debugstr_variant(&data) );
270 return E_NOTIMPL;
273 static HRESULT WINAPI field_GetChunk( Field *iface, LONG length, VARIANT *var )
275 FIXME( "%p, %d, %p\n", iface, length, var );
276 return E_NOTIMPL;
279 static HRESULT WINAPI field_get_OriginalValue( Field *iface, VARIANT *val )
281 FIXME( "%p, %p\n", iface, val );
282 return E_NOTIMPL;
285 static HRESULT WINAPI field_get_UnderlyingValue( Field *iface, VARIANT *val )
287 FIXME( "%p, %p\n", iface, val );
288 return E_NOTIMPL;
291 static HRESULT WINAPI field_get_DataFormat( Field *iface, IUnknown **format )
293 FIXME( "%p, %p\n", iface, format );
294 return E_NOTIMPL;
297 static HRESULT WINAPI field_putref_DataFormat( Field *iface, IUnknown *format )
299 FIXME( "%p, %p\n", iface, format );
300 return E_NOTIMPL;
303 static HRESULT WINAPI field_put_Precision( Field *iface, unsigned char precision )
305 FIXME( "%p, %c\n", iface, precision );
306 return E_NOTIMPL;
309 static HRESULT WINAPI field_put_NumericScale( Field *iface, unsigned char scale )
311 FIXME( "%p, %c\n", iface, scale );
312 return E_NOTIMPL;
315 static HRESULT WINAPI field_put_Type( Field *iface, DataTypeEnum type )
317 struct field *field = impl_from_Field( iface );
319 TRACE( "%p, %u\n", field, type );
321 field->type = type;
322 return S_OK;
325 static HRESULT WINAPI field_put_DefinedSize( Field *iface, LONG size )
327 struct field *field = impl_from_Field( iface );
329 TRACE( "%p, %d\n", field, size );
331 field->defined_size = size;
332 return S_OK;
335 static HRESULT WINAPI field_put_Attributes( Field *iface, LONG attrs )
337 struct field *field = impl_from_Field( iface );
339 TRACE( "%p, %d\n", field, attrs );
341 field->attrs = attrs;
342 return S_OK;
345 static HRESULT WINAPI field_get_Status( Field *iface, LONG *status )
347 FIXME( "%p, %p\n", iface, status );
348 return E_NOTIMPL;
351 static const struct FieldVtbl field_vtbl =
353 field_QueryInterface,
354 field_AddRef,
355 field_Release,
356 field_GetTypeInfoCount,
357 field_GetTypeInfo,
358 field_GetIDsOfNames,
359 field_Invoke,
360 field_get_Properties,
361 field_get_ActualSize,
362 field_get_Attributes,
363 field_get_DefinedSize,
364 field_get_Name,
365 field_get_Type,
366 field_get_Value,
367 field_put_Value,
368 field_get_Precision,
369 field_get_NumericScale,
370 field_AppendChunk,
371 field_GetChunk,
372 field_get_OriginalValue,
373 field_get_UnderlyingValue,
374 field_get_DataFormat,
375 field_putref_DataFormat,
376 field_put_Precision,
377 field_put_NumericScale,
378 field_put_Type,
379 field_put_DefinedSize,
380 field_put_Attributes,
381 field_get_Status
384 static inline struct field *field_from_ISupportErrorInfo( ISupportErrorInfo *iface )
386 return CONTAINING_RECORD( iface, struct field, ISupportErrorInfo_iface );
389 static HRESULT WINAPI field_supporterrorinfo_QueryInterface( ISupportErrorInfo *iface, REFIID riid, void **obj )
391 struct field *field = field_from_ISupportErrorInfo( iface );
392 return Field_QueryInterface( &field->Field_iface, riid, obj );
395 static ULONG WINAPI field_supporterrorinfo_AddRef( ISupportErrorInfo *iface )
397 struct field *field = field_from_ISupportErrorInfo( iface );
398 return Field_AddRef( &field->Field_iface );
401 static ULONG WINAPI field_supporterrorinfo_Release( ISupportErrorInfo *iface )
403 struct field *field = field_from_ISupportErrorInfo( iface );
404 return Field_Release( &field->Field_iface );
407 static HRESULT WINAPI field_supporterrorinfo_InterfaceSupportsErrorInfo( ISupportErrorInfo *iface, REFIID riid )
409 struct field *field = field_from_ISupportErrorInfo( iface );
410 FIXME( "%p, %s\n", field, debugstr_guid(riid) );
411 return S_FALSE;
414 static const ISupportErrorInfoVtbl field_supporterrorinfo_vtbl =
416 field_supporterrorinfo_QueryInterface,
417 field_supporterrorinfo_AddRef,
418 field_supporterrorinfo_Release,
419 field_supporterrorinfo_InterfaceSupportsErrorInfo
422 static HRESULT Field_create( const WCHAR *name, LONG index, struct recordset *recordset, Field **obj )
424 struct field *field;
426 if (!(field = heap_alloc_zero( sizeof(*field) ))) return E_OUTOFMEMORY;
427 field->Field_iface.lpVtbl = &field_vtbl;
428 field->ISupportErrorInfo_iface.lpVtbl = &field_supporterrorinfo_vtbl;
429 if (!(field->name = strdupW( name )))
431 heap_free( field );
432 return E_OUTOFMEMORY;
434 field->index = index;
435 field->recordset = recordset;
437 *obj = &field->Field_iface;
438 TRACE( "returning iface %p\n", *obj );
439 return S_OK;
442 static inline struct fields *impl_from_Fields( Fields *iface )
444 return CONTAINING_RECORD( iface, struct fields, Fields_iface );
447 static ULONG WINAPI fields_AddRef( Fields *iface )
449 struct fields *fields = impl_from_Fields( iface );
450 LONG refs = InterlockedIncrement( &fields->refs );
451 TRACE( "%p new refcount %d\n", fields, refs );
452 return refs;
455 static ULONG WINAPI fields_Release( Fields *iface )
457 struct fields *fields = impl_from_Fields( iface );
458 LONG refs = InterlockedDecrement( &fields->refs );
459 TRACE( "%p new refcount %d\n", fields, refs );
460 if (!refs)
462 if (fields->recordset) _Recordset_Release( &fields->recordset->Recordset_iface );
463 WARN( "not destroying %p\n", fields );
464 return InterlockedIncrement( &fields->refs );
466 return refs;
469 static HRESULT WINAPI fields_QueryInterface( Fields *iface, REFIID riid, void **obj )
471 struct fields *fields = impl_from_Fields( iface );
472 TRACE( "%p, %s, %p\n", iface, debugstr_guid(riid), obj );
474 if (IsEqualGUID( riid, &IID_Fields ) || IsEqualGUID( riid, &IID_IDispatch ) ||
475 IsEqualGUID( riid, &IID_IUnknown ))
477 *obj = iface;
479 else if (IsEqualGUID( riid, &IID_ISupportErrorInfo ))
481 *obj = &fields->ISupportErrorInfo_iface;
483 else
485 FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
486 return E_NOINTERFACE;
488 fields_AddRef( iface );
489 return S_OK;
492 static HRESULT WINAPI fields_GetTypeInfoCount( Fields *iface, UINT *count )
494 FIXME( "%p, %p\n", iface, count );
495 return E_NOTIMPL;
498 static HRESULT WINAPI fields_GetTypeInfo( Fields *iface, UINT index, LCID lcid, ITypeInfo **info )
500 FIXME( "%p, %u, %u, %p\n", iface, index, lcid, info );
501 return E_NOTIMPL;
504 static HRESULT WINAPI fields_GetIDsOfNames( Fields *iface, REFIID riid, LPOLESTR *names, UINT count,
505 LCID lcid, DISPID *dispid )
507 FIXME( "%p, %s, %p, %u, %u, %p\n", iface, debugstr_guid(riid), names, count, lcid, dispid );
508 return E_NOTIMPL;
511 static HRESULT WINAPI fields_Invoke( Fields *iface, DISPID member, REFIID riid, LCID lcid, WORD flags,
512 DISPPARAMS *params, VARIANT *result, EXCEPINFO *excep_info, UINT *arg_err )
514 FIXME( "%p, %d, %s, %d, %d, %p, %p, %p, %p\n", iface, member, debugstr_guid(riid), lcid, flags, params,
515 result, excep_info, arg_err );
516 return E_NOTIMPL;
519 static HRESULT WINAPI fields_get_Count( Fields *iface, LONG *count )
521 struct fields *fields = impl_from_Fields( iface );
523 TRACE( "%p, %p\n", fields, count );
525 *count = fields->count;
526 return S_OK;
529 static HRESULT WINAPI fields__NewEnum( Fields *iface, IUnknown **obj )
531 FIXME( "%p, %p\n", iface, obj );
532 return E_NOTIMPL;
535 static HRESULT WINAPI fields_Refresh( Fields *iface )
537 FIXME( "%p\n", iface );
538 return E_NOTIMPL;
541 static HRESULT map_index( struct fields *fields, VARIANT *index, ULONG *ret )
543 ULONG i;
545 if (V_VT( index ) != VT_BSTR)
547 FIXME( "variant type %u not supported\n", V_VT( index ) );
548 return E_INVALIDARG;
551 for (i = 0; i < fields->count; i++)
553 BSTR name;
554 BOOL match;
555 HRESULT hr;
557 if ((hr = Field_get_Name( fields->field[i], &name )) != S_OK) return hr;
558 match = !wcsicmp( V_BSTR( index ), name );
559 SysFreeString( name );
560 if (match)
562 *ret = i;
563 return S_OK;
567 return E_INVALIDARG;
570 static HRESULT WINAPI fields_get_Item( Fields *iface, VARIANT index, Field **obj )
572 struct fields *fields = impl_from_Fields( iface );
573 HRESULT hr;
574 ULONG i;
576 TRACE( "%p, %s, %p\n", fields, debugstr_variant(&index), obj );
578 if ((hr = map_index( fields, &index, &i )) != S_OK) return hr;
580 Field_AddRef( fields->field[i] );
581 *obj = fields->field[i];
582 return S_OK;
585 static BOOL resize_fields( struct fields *fields, ULONG count )
587 if (count > fields->allocated)
589 Field **tmp;
590 ULONG new_size = max( count, fields->allocated * 2 );
591 if (!(tmp = heap_realloc( fields->field, new_size * sizeof(*tmp) ))) return FALSE;
592 fields->field = tmp;
593 fields->allocated = new_size;
596 fields->count = count;
597 return TRUE;
600 static HRESULT append_field( struct fields *fields, BSTR name, DataTypeEnum type, LONG size, FieldAttributeEnum attr,
601 VARIANT *value )
603 Field *field;
604 HRESULT hr;
606 if ((hr = Field_create( name, fields->count, fields->recordset, &field )) != S_OK) return hr;
607 Field_put_Type( field, type );
608 Field_put_DefinedSize( field, size );
609 if (attr != adFldUnspecified) Field_put_Attributes( field, attr );
610 if (value) FIXME( "ignoring value %s\n", debugstr_variant(value) );
612 if (!(resize_fields( fields, fields->count + 1 )))
614 Field_Release( field );
615 return E_OUTOFMEMORY;
618 fields->field[fields->count - 1] = field;
619 return S_OK;
622 static HRESULT WINAPI fields__Append( Fields *iface, BSTR name, DataTypeEnum type, LONG size, FieldAttributeEnum attr )
624 struct fields *fields = impl_from_Fields( iface );
626 TRACE( "%p, %s, %u, %d, %d\n", fields, debugstr_w(name), type, size, attr );
628 return append_field( fields, name, type, size, attr, NULL );
631 static HRESULT WINAPI fields_Delete( Fields *iface, VARIANT index )
633 FIXME( "%p, %s\n", iface, debugstr_variant(&index) );
634 return E_NOTIMPL;
637 static HRESULT WINAPI fields_Append( Fields *iface, BSTR name, DataTypeEnum type, LONG size, FieldAttributeEnum attr,
638 VARIANT value )
640 struct fields *fields = impl_from_Fields( iface );
642 TRACE( "%p, %s, %u, %d, %d, %s\n", fields, debugstr_w(name), type, size, attr, debugstr_variant(&value) );
644 return append_field( fields, name, type, size, attr, &value );
647 static HRESULT WINAPI fields_Update( Fields *iface )
649 FIXME( "%p\n", iface );
650 return E_NOTIMPL;
653 static HRESULT WINAPI fields_Resync( Fields *iface, ResyncEnum resync_values )
655 FIXME( "%p, %u\n", iface, resync_values );
656 return E_NOTIMPL;
659 static HRESULT WINAPI fields_CancelUpdate( Fields *iface )
661 FIXME( "%p\n", iface );
662 return E_NOTIMPL;
665 static const struct FieldsVtbl fields_vtbl =
667 fields_QueryInterface,
668 fields_AddRef,
669 fields_Release,
670 fields_GetTypeInfoCount,
671 fields_GetTypeInfo,
672 fields_GetIDsOfNames,
673 fields_Invoke,
674 fields_get_Count,
675 fields__NewEnum,
676 fields_Refresh,
677 fields_get_Item,
678 fields__Append,
679 fields_Delete,
680 fields_Append,
681 fields_Update,
682 fields_Resync,
683 fields_CancelUpdate
686 static inline struct fields *fields_from_ISupportErrorInfo( ISupportErrorInfo *iface )
688 return CONTAINING_RECORD( iface, struct fields, ISupportErrorInfo_iface );
691 static HRESULT WINAPI fields_supporterrorinfo_QueryInterface( ISupportErrorInfo *iface, REFIID riid, void **obj )
693 struct fields *fields = fields_from_ISupportErrorInfo( iface );
694 return Fields_QueryInterface( &fields->Fields_iface, riid, obj );
697 static ULONG WINAPI fields_supporterrorinfo_AddRef( ISupportErrorInfo *iface )
699 struct fields *fields = fields_from_ISupportErrorInfo( iface );
700 return Fields_AddRef( &fields->Fields_iface );
703 static ULONG WINAPI fields_supporterrorinfo_Release( ISupportErrorInfo *iface )
705 struct fields *fields = fields_from_ISupportErrorInfo( iface );
706 return Fields_Release( &fields->Fields_iface );
709 static HRESULT WINAPI fields_supporterrorinfo_InterfaceSupportsErrorInfo( ISupportErrorInfo *iface, REFIID riid )
711 struct fields *fields = fields_from_ISupportErrorInfo( iface );
712 FIXME( "%p, %s\n", fields, debugstr_guid(riid) );
713 return S_FALSE;
716 static const ISupportErrorInfoVtbl fields_supporterrorinfo_vtbl =
718 fields_supporterrorinfo_QueryInterface,
719 fields_supporterrorinfo_AddRef,
720 fields_supporterrorinfo_Release,
721 fields_supporterrorinfo_InterfaceSupportsErrorInfo
724 static HRESULT fields_create( struct recordset *recordset, struct fields **ret )
726 struct fields *fields;
728 if (!(fields = heap_alloc_zero( sizeof(*fields) ))) return E_OUTOFMEMORY;
729 fields->Fields_iface.lpVtbl = &fields_vtbl;
730 fields->ISupportErrorInfo_iface.lpVtbl = &fields_supporterrorinfo_vtbl;
731 fields->refs = 1;
732 fields->recordset = recordset;
733 _Recordset_AddRef( &fields->recordset->Recordset_iface );
735 *ret = fields;
736 TRACE( "returning %p\n", *ret );
737 return S_OK;
740 static inline struct recordset *impl_from_Recordset( _Recordset *iface )
742 return CONTAINING_RECORD( iface, struct recordset, Recordset_iface );
745 static inline struct recordset *impl_from_ADORecordsetConstruction( ADORecordsetConstruction *iface )
747 return CONTAINING_RECORD( iface, struct recordset, ADORecordsetConstruction_iface );
750 static ULONG WINAPI recordset_AddRef( _Recordset *iface )
752 struct recordset *recordset = impl_from_Recordset( iface );
753 LONG refs = InterlockedIncrement( &recordset->refs );
754 TRACE( "%p new refcount %d\n", recordset, refs );
755 return refs;
758 static void close_recordset( struct recordset *recordset )
760 ULONG row, col, col_count;
762 if ( recordset->row_set ) IRowset_Release( recordset->row_set );
763 recordset->row_set = NULL;
765 if (!recordset->fields) return;
766 col_count = get_column_count( recordset );
768 recordset->fields->recordset = NULL;
769 Fields_Release( &recordset->fields->Fields_iface );
770 recordset->fields = NULL;
772 for (row = 0; row < recordset->count; row++)
773 for (col = 0; col < col_count; col++) VariantClear( &recordset->data[row * col_count + col] );
775 recordset->count = recordset->allocated = recordset->index = 0;
776 heap_free( recordset->data );
777 recordset->data = NULL;
780 static ULONG WINAPI recordset_Release( _Recordset *iface )
782 struct recordset *recordset = impl_from_Recordset( iface );
783 LONG refs = InterlockedDecrement( &recordset->refs );
784 TRACE( "%p new refcount %d\n", recordset, refs );
785 if (!refs)
787 TRACE( "destroying %p\n", recordset );
788 close_recordset( recordset );
789 heap_free( recordset );
791 return refs;
794 static HRESULT WINAPI recordset_QueryInterface( _Recordset *iface, REFIID riid, void **obj )
796 struct recordset *recordset = impl_from_Recordset( iface );
797 TRACE( "%p, %s, %p\n", iface, debugstr_guid(riid), obj );
799 *obj = NULL;
801 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch) ||
802 IsEqualIID(riid, &IID__ADO) || IsEqualIID(riid, &IID_Recordset15) ||
803 IsEqualIID(riid, &IID_Recordset20) || IsEqualIID(riid, &IID_Recordset21) ||
804 IsEqualIID(riid, &IID__Recordset))
806 *obj = iface;
808 else if (IsEqualGUID( riid, &IID_ISupportErrorInfo ))
810 *obj = &recordset->ISupportErrorInfo_iface;
812 else if (IsEqualGUID( riid, &IID_ADORecordsetConstruction ))
814 *obj = &recordset->ADORecordsetConstruction_iface;
816 else if (IsEqualGUID( riid, &IID_IRunnableObject ))
818 TRACE("IID_IRunnableObject not supported returning NULL\n");
819 return E_NOINTERFACE;
821 else
823 FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
824 return E_NOINTERFACE;
826 recordset_AddRef( iface );
827 return S_OK;
830 static HRESULT WINAPI recordset_GetTypeInfoCount( _Recordset *iface, UINT *count )
832 FIXME( "%p, %p\n", iface, count );
833 return E_NOTIMPL;
836 static HRESULT WINAPI recordset_GetTypeInfo( _Recordset *iface, UINT index, LCID lcid, ITypeInfo **info )
838 FIXME( "%p, %u, %u, %p\n", iface, index, lcid, info );
839 return E_NOTIMPL;
842 static HRESULT WINAPI recordset_GetIDsOfNames( _Recordset *iface, REFIID riid, LPOLESTR *names, UINT count,
843 LCID lcid, DISPID *dispid )
845 FIXME( "%p, %s, %p, %u, %u, %p\n", iface, debugstr_guid(riid), names, count, lcid, dispid );
846 return E_NOTIMPL;
849 static HRESULT WINAPI recordset_Invoke( _Recordset *iface, DISPID member, REFIID riid, LCID lcid, WORD flags,
850 DISPPARAMS *params, VARIANT *result, EXCEPINFO *excep_info, UINT *arg_err )
852 FIXME( "%p, %d, %s, %d, %d, %p, %p, %p, %p\n", iface, member, debugstr_guid(riid), lcid, flags, params,
853 result, excep_info, arg_err );
854 return E_NOTIMPL;
857 static HRESULT WINAPI recordset_get_Properties( _Recordset *iface, Properties **obj )
859 FIXME( "%p, %p\n", iface, obj );
860 return E_NOTIMPL;
863 static HRESULT WINAPI recordset_get_AbsolutePosition( _Recordset *iface, PositionEnum_Param *pos )
865 FIXME( "%p, %p\n", iface, pos );
866 return E_NOTIMPL;
869 static HRESULT WINAPI recordset_put_AbsolutePosition( _Recordset *iface, PositionEnum_Param pos )
871 FIXME( "%p, %d\n", iface, pos );
872 return E_NOTIMPL;
875 static HRESULT WINAPI recordset_putref_ActiveConnection( _Recordset *iface, IDispatch *connection )
877 FIXME( "%p, %p\n", iface, connection );
878 return E_NOTIMPL;
881 static HRESULT WINAPI recordset_put_ActiveConnection( _Recordset *iface, VARIANT connection )
883 FIXME( "%p, %s\n", iface, debugstr_variant(&connection) );
884 return E_NOTIMPL;
887 static HRESULT WINAPI recordset_get_ActiveConnection( _Recordset *iface, VARIANT *connection )
889 FIXME( "%p, %p\n", iface, connection );
890 return E_NOTIMPL;
893 static HRESULT WINAPI recordset_get_BOF( _Recordset *iface, VARIANT_BOOL *bof )
895 struct recordset *recordset = impl_from_Recordset( iface );
897 TRACE( "%p, %p\n", recordset, bof );
899 *bof = (recordset->index < 0) ? VARIANT_TRUE : VARIANT_FALSE;
900 return S_OK;
903 static HRESULT WINAPI recordset_get_Bookmark( _Recordset *iface, VARIANT *bookmark )
905 FIXME( "%p, %p\n", iface, bookmark );
906 return E_NOTIMPL;
909 static HRESULT WINAPI recordset_put_Bookmark( _Recordset *iface, VARIANT bookmark )
911 FIXME( "%p, %s\n", iface, debugstr_variant(&bookmark) );
912 return E_NOTIMPL;
915 static HRESULT WINAPI recordset_get_CacheSize( _Recordset *iface, LONG *size )
917 FIXME( "%p, %p\n", iface, size );
918 return E_NOTIMPL;
921 static HRESULT WINAPI recordset_put_CacheSize( _Recordset *iface, LONG size )
923 FIXME( "%p, %d\n", iface, size );
924 return E_NOTIMPL;
927 static HRESULT WINAPI recordset_get_CursorType( _Recordset *iface, CursorTypeEnum *cursor_type )
929 struct recordset *recordset = impl_from_Recordset( iface );
931 TRACE( "%p, %p\n", iface, cursor_type );
933 *cursor_type = recordset->cursor_type;
934 return S_OK;
937 static HRESULT WINAPI recordset_put_CursorType( _Recordset *iface, CursorTypeEnum cursor_type )
939 struct recordset *recordset = impl_from_Recordset( iface );
941 TRACE( "%p, %d\n", iface, cursor_type );
943 recordset->cursor_type = cursor_type;
944 return S_OK;
947 static HRESULT WINAPI recordset_get_EOF( _Recordset *iface, VARIANT_BOOL *eof )
949 struct recordset *recordset = impl_from_Recordset( iface );
951 TRACE( "%p, %p\n", recordset, eof );
953 *eof = (!recordset->count || recordset->index >= recordset->count) ? VARIANT_TRUE : VARIANT_FALSE;
954 return S_OK;
957 static HRESULT WINAPI recordset_get_Fields( _Recordset *iface, Fields **obj )
959 struct recordset *recordset = impl_from_Recordset( iface );
960 HRESULT hr;
962 TRACE( "%p, %p\n", recordset, obj );
964 if (recordset->fields)
966 /* yes, this adds a reference to the recordset instead of the fields object */
967 _Recordset_AddRef( &recordset->Recordset_iface );
968 *obj = &recordset->fields->Fields_iface;
969 return S_OK;
972 if ((hr = fields_create( recordset, &recordset->fields )) != S_OK) return hr;
974 *obj = &recordset->fields->Fields_iface;
975 return S_OK;
978 static HRESULT WINAPI recordset_get_LockType( _Recordset *iface, LockTypeEnum *lock_type )
980 FIXME( "%p, %p\n", iface, lock_type );
981 return E_NOTIMPL;
984 static HRESULT WINAPI recordset_put_LockType( _Recordset *iface, LockTypeEnum lock_type )
986 FIXME( "%p, %d\n", iface, lock_type );
987 return E_NOTIMPL;
990 static HRESULT WINAPI recordset_get_MaxRecords( _Recordset *iface, LONG *max_records )
992 FIXME( "%p, %p\n", iface, max_records );
993 return E_NOTIMPL;
996 static HRESULT WINAPI recordset_put_MaxRecords( _Recordset *iface, LONG max_records )
998 FIXME( "%p, %d\n", iface, max_records );
999 return E_NOTIMPL;
1002 static HRESULT WINAPI recordset_get_RecordCount( _Recordset *iface, LONG *count )
1004 struct recordset *recordset = impl_from_Recordset( iface );
1006 TRACE( "%p, %p\n", recordset, count );
1008 *count = recordset->count;
1009 return S_OK;
1012 static HRESULT WINAPI recordset_putref_Source( _Recordset *iface, IDispatch *source )
1014 FIXME( "%p, %p\n", iface, source );
1015 return E_NOTIMPL;
1018 static HRESULT WINAPI recordset_put_Source( _Recordset *iface, BSTR source )
1020 FIXME( "%p, %s\n", iface, debugstr_w(source) );
1021 return E_NOTIMPL;
1024 static HRESULT WINAPI recordset_get_Source( _Recordset *iface, VARIANT *source )
1026 FIXME( "%p, %p\n", iface, source );
1027 return E_NOTIMPL;
1030 static BOOL resize_recordset( struct recordset *recordset, ULONG row_count )
1032 ULONG row_size = get_column_count( recordset ) * sizeof(*recordset->data);
1034 if (row_count > recordset->allocated)
1036 VARIANT *tmp;
1037 ULONG count = max( row_count, recordset->allocated * 2 );
1038 if (!(tmp = heap_realloc_zero( recordset->data, count * row_size ))) return FALSE;
1039 recordset->data = tmp;
1040 recordset->allocated = count;
1043 recordset->count = row_count;
1044 return TRUE;
1047 static HRESULT WINAPI recordset_AddNew( _Recordset *iface, VARIANT field_list, VARIANT values )
1049 struct recordset *recordset = impl_from_Recordset( iface );
1051 TRACE( "%p, %s, %s\n", recordset, debugstr_variant(&field_list), debugstr_variant(&values) );
1052 FIXME( "ignoring field list and values\n" );
1054 if (recordset->state == adStateClosed) return MAKE_ADO_HRESULT( adErrObjectClosed );
1056 if (!resize_recordset( recordset, recordset->count + 1 )) return E_OUTOFMEMORY;
1057 recordset->index++;
1058 return S_OK;
1061 static HRESULT WINAPI recordset_CancelUpdate( _Recordset *iface )
1063 FIXME( "%p\n", iface );
1064 return E_NOTIMPL;
1067 static HRESULT WINAPI recordset_Close( _Recordset *iface )
1069 struct recordset *recordset = impl_from_Recordset( iface );
1071 TRACE( "%p\n", recordset );
1073 if (recordset->state == adStateClosed) return MAKE_ADO_HRESULT( adErrObjectClosed );
1075 close_recordset( recordset );
1076 recordset->state = adStateClosed;
1077 return S_OK;
1080 static HRESULT WINAPI recordset_Delete( _Recordset *iface, AffectEnum affect_records )
1082 FIXME( "%p, %u\n", iface, affect_records );
1083 return E_NOTIMPL;
1086 static HRESULT WINAPI recordset_GetRows( _Recordset *iface, LONG rows, VARIANT start, VARIANT fields, VARIANT *var )
1088 FIXME( "%p, %d, %s, %s, %p\n", iface, rows, debugstr_variant(&start), debugstr_variant(&fields), var );
1089 return E_NOTIMPL;
1092 static HRESULT WINAPI recordset_Move( _Recordset *iface, LONG num_records, VARIANT start )
1094 FIXME( "%p, %d, %s\n", iface, num_records, debugstr_variant(&start) );
1095 return E_NOTIMPL;
1098 static HRESULT WINAPI recordset_MoveNext( _Recordset *iface )
1100 struct recordset *recordset = impl_from_Recordset( iface );
1102 TRACE( "%p\n", recordset );
1104 if (recordset->index < recordset->count) recordset->index++;
1105 return S_OK;
1108 static HRESULT WINAPI recordset_MovePrevious( _Recordset *iface )
1110 struct recordset *recordset = impl_from_Recordset( iface );
1112 TRACE( "%p\n", recordset );
1114 if (recordset->index >= 0) recordset->index--;
1115 return S_OK;
1118 static HRESULT WINAPI recordset_MoveFirst( _Recordset *iface )
1120 struct recordset *recordset = impl_from_Recordset( iface );
1122 TRACE( "%p\n", recordset );
1124 recordset->index = 0;
1125 return S_OK;
1128 static HRESULT WINAPI recordset_MoveLast( _Recordset *iface )
1130 struct recordset *recordset = impl_from_Recordset( iface );
1132 TRACE( "%p\n", recordset );
1134 recordset->index = (recordset->count > 0) ? recordset->count - 1 : 0;
1135 return S_OK;
1138 static HRESULT WINAPI recordset_Open( _Recordset *iface, VARIANT source, VARIANT active_connection,
1139 CursorTypeEnum cursor_type, LockTypeEnum lock_type, LONG options )
1141 struct recordset *recordset = impl_from_Recordset( iface );
1143 FIXME( "%p, %s, %s, %d, %d, %d\n", recordset, debugstr_variant(&source), debugstr_variant(&active_connection),
1144 cursor_type, lock_type, options );
1146 if (!recordset->fields) return MAKE_ADO_HRESULT( adErrInvalidConnection );
1147 if (recordset->state == adStateOpen) return MAKE_ADO_HRESULT( adErrObjectOpen );
1149 recordset->state = adStateOpen;
1150 return S_OK;
1153 static HRESULT WINAPI recordset_Requery( _Recordset *iface, LONG options )
1155 FIXME( "%p, %d\n", iface, options );
1156 return E_NOTIMPL;
1159 static HRESULT WINAPI recordset__xResync( _Recordset *iface, AffectEnum affect_records )
1161 FIXME( "%p, %u\n", iface, affect_records );
1162 return E_NOTIMPL;
1165 static HRESULT WINAPI recordset_Update( _Recordset *iface, VARIANT fields, VARIANT values )
1167 FIXME( "%p, %s, %s\n", iface, debugstr_variant(&fields), debugstr_variant(&values) );
1168 return E_NOTIMPL;
1171 static HRESULT WINAPI recordset_get_AbsolutePage( _Recordset *iface, PositionEnum_Param *pos )
1173 FIXME( "%p, %p\n", iface, pos );
1174 return E_NOTIMPL;
1177 static HRESULT WINAPI recordset_put_AbsolutePage( _Recordset *iface, PositionEnum_Param pos )
1179 FIXME( "%p, %d\n", iface, pos );
1180 return E_NOTIMPL;
1183 static HRESULT WINAPI recordset_get_EditMode( _Recordset *iface, EditModeEnum *mode )
1185 FIXME( "%p, %p\n", iface, mode );
1186 return E_NOTIMPL;
1189 static HRESULT WINAPI recordset_get_Filter( _Recordset *iface, VARIANT *criteria )
1191 FIXME( "%p, %p\n", iface, criteria );
1192 return E_NOTIMPL;
1195 static HRESULT WINAPI recordset_put_Filter( _Recordset *iface, VARIANT criteria )
1197 FIXME( "%p, %s\n", iface, debugstr_variant(&criteria) );
1198 return E_NOTIMPL;
1201 static HRESULT WINAPI recordset_get_PageCount( _Recordset *iface, LONG *count )
1203 FIXME( "%p, %p\n", iface, count );
1204 return E_NOTIMPL;
1207 static HRESULT WINAPI recordset_get_PageSize( _Recordset *iface, LONG *size )
1209 FIXME( "%p, %p\n", iface, size );
1210 return E_NOTIMPL;
1213 static HRESULT WINAPI recordset_put_PageSize( _Recordset *iface, LONG size )
1215 FIXME( "%p, %d\n", iface, size );
1216 return E_NOTIMPL;
1219 static HRESULT WINAPI recordset_get_Sort( _Recordset *iface, BSTR *criteria )
1221 FIXME( "%p, %p\n", iface, criteria );
1222 return E_NOTIMPL;
1225 static HRESULT WINAPI recordset_put_Sort( _Recordset *iface, BSTR criteria )
1227 FIXME( "%p, %s\n", iface, debugstr_w(criteria) );
1228 return E_NOTIMPL;
1231 static HRESULT WINAPI recordset_get_Status( _Recordset *iface, LONG *status )
1233 FIXME( "%p, %p\n", iface, status );
1234 return E_NOTIMPL;
1237 static HRESULT WINAPI recordset_get_State( _Recordset *iface, LONG *state )
1239 struct recordset *recordset = impl_from_Recordset( iface );
1241 TRACE( "%p, %p\n", recordset, state );
1243 *state = recordset->state;
1244 return S_OK;
1247 static HRESULT WINAPI recordset__xClone( _Recordset *iface, _Recordset **obj )
1249 FIXME( "%p, %p\n", iface, obj );
1250 return E_NOTIMPL;
1253 static HRESULT WINAPI recordset_UpdateBatch( _Recordset *iface, AffectEnum affect_records )
1255 FIXME( "%p, %u\n", iface, affect_records );
1256 return E_NOTIMPL;
1259 static HRESULT WINAPI recordset_CancelBatch( _Recordset *iface, AffectEnum affect_records )
1261 FIXME( "%p, %u\n", iface, affect_records );
1262 return E_NOTIMPL;
1265 static HRESULT WINAPI recordset_get_CursorLocation( _Recordset *iface, CursorLocationEnum *cursor_loc )
1267 struct recordset *recordset = impl_from_Recordset( iface );
1269 TRACE( "%p, %p\n", iface, cursor_loc );
1271 *cursor_loc = recordset->cursor_location;
1273 return S_OK;
1276 static HRESULT WINAPI recordset_put_CursorLocation( _Recordset *iface, CursorLocationEnum cursor_loc )
1278 struct recordset *recordset = impl_from_Recordset( iface );
1280 TRACE( "%p, %u\n", iface, cursor_loc );
1282 if (recordset->state == adStateOpen) return MAKE_ADO_HRESULT( adErrObjectOpen );
1284 recordset->cursor_location = cursor_loc;
1286 return S_OK;
1289 static HRESULT WINAPI recordset_NextRecordset( _Recordset *iface, VARIANT *records_affected, _Recordset **record_set )
1291 FIXME( "%p, %p, %p\n", iface, records_affected, record_set );
1292 return E_NOTIMPL;
1295 static HRESULT WINAPI recordset_Supports( _Recordset *iface, CursorOptionEnum cursor_options, VARIANT_BOOL *ret )
1297 FIXME( "%p, %08x, %p\n", iface, cursor_options, ret );
1298 return E_NOTIMPL;
1301 static HRESULT WINAPI recordset_get_Collect( _Recordset *iface, VARIANT index, VARIANT *var )
1303 FIXME( "%p, %s, %p\n", iface, debugstr_variant(&index), var );
1304 return E_NOTIMPL;
1307 static HRESULT WINAPI recordset_put_Collect( _Recordset *iface, VARIANT index, VARIANT var )
1309 FIXME( "%p, %s, %s\n", iface, debugstr_variant(&index), debugstr_variant(&var) );
1310 return E_NOTIMPL;
1313 static HRESULT WINAPI recordset_get_MarshalOptions( _Recordset *iface, MarshalOptionsEnum *options )
1315 FIXME( "%p, %p\n", iface, options );
1316 return E_NOTIMPL;
1319 static HRESULT WINAPI recordset_put_MarshalOptions( _Recordset *iface, MarshalOptionsEnum options )
1321 FIXME( "%p, %u\n", iface, options );
1322 return E_NOTIMPL;
1325 static HRESULT WINAPI recordset_Find( _Recordset *iface, BSTR criteria, LONG skip_records,
1326 SearchDirectionEnum search_direction, VARIANT start )
1328 FIXME( "%p, %s, %d, %d, %s\n", iface, debugstr_w(criteria), skip_records, search_direction,
1329 debugstr_variant(&start) );
1330 return E_NOTIMPL;
1333 static HRESULT WINAPI recordset_Cancel( _Recordset *iface )
1335 FIXME( "%p\n", iface );
1336 return E_NOTIMPL;
1339 static HRESULT WINAPI recordset_get_DataSource( _Recordset *iface, IUnknown **data_source )
1341 FIXME( "%p, %p\n", iface, data_source );
1342 return E_NOTIMPL;
1345 static HRESULT WINAPI recordset_putref_DataSource( _Recordset *iface, IUnknown *data_source )
1347 FIXME( "%p, %p\n", iface, data_source );
1348 return E_NOTIMPL;
1351 static HRESULT WINAPI recordset__xSave( _Recordset *iface, BSTR filename, PersistFormatEnum persist_format )
1353 FIXME( "%p, %s, %u\n", iface, debugstr_w(filename), persist_format );
1354 return E_NOTIMPL;
1357 static HRESULT WINAPI recordset_get_ActiveCommand( _Recordset *iface, IDispatch **cmd )
1359 FIXME( "%p, %p\n", iface, cmd );
1360 return E_NOTIMPL;
1363 static HRESULT WINAPI recordset_put_StayInSync( _Recordset *iface, VARIANT_BOOL stay_in_sync )
1365 FIXME( "%p, %d\n", iface, stay_in_sync );
1366 return E_NOTIMPL;
1369 static HRESULT WINAPI recordset_get_StayInSync( _Recordset *iface, VARIANT_BOOL *stay_in_sync )
1371 FIXME( "%p, %p\n", iface, stay_in_sync );
1372 return E_NOTIMPL;
1375 static HRESULT WINAPI recordset_GetString( _Recordset *iface, StringFormatEnum string_format, LONG num_rows,
1376 BSTR column_delimiter, BSTR row_delimiter, BSTR null_expr,
1377 BSTR *ret_string )
1379 FIXME( "%p, %u, %d, %s, %s, %s, %p\n", iface, string_format, num_rows, debugstr_w(column_delimiter),
1380 debugstr_w(row_delimiter), debugstr_w(null_expr), ret_string );
1381 return E_NOTIMPL;
1384 static HRESULT WINAPI recordset_get_DataMember( _Recordset *iface, BSTR *data_member )
1386 FIXME( "%p, %p\n", iface, data_member );
1387 return E_NOTIMPL;
1390 static HRESULT WINAPI recordset_put_DataMember( _Recordset *iface, BSTR data_member )
1392 FIXME( "%p, %s\n", iface, debugstr_w(data_member) );
1393 return E_NOTIMPL;
1396 static HRESULT WINAPI recordset_CompareBookmarks( _Recordset *iface, VARIANT bookmark1, VARIANT bookmark2, CompareEnum *compare )
1398 FIXME( "%p, %s, %s, %p\n", iface, debugstr_variant(&bookmark1), debugstr_variant(&bookmark2), compare );
1399 return E_NOTIMPL;
1402 static HRESULT WINAPI recordset_Clone( _Recordset *iface, LockTypeEnum lock_type, _Recordset **obj )
1404 FIXME( "%p, %d, %p\n", iface, lock_type, obj );
1405 return E_NOTIMPL;
1408 static HRESULT WINAPI recordset_Resync( _Recordset *iface, AffectEnum affect_records, ResyncEnum resync_values )
1410 FIXME( "%p, %u, %u\n", iface, affect_records, resync_values );
1411 return E_NOTIMPL;
1414 static HRESULT WINAPI recordset_Seek( _Recordset *iface, VARIANT key_values, SeekEnum seek_option )
1416 FIXME( "%p, %s, %u\n", iface, debugstr_variant(&key_values), seek_option );
1417 return E_NOTIMPL;
1420 static HRESULT WINAPI recordset_put_Index( _Recordset *iface, BSTR index )
1422 FIXME( "%p, %s\n", iface, debugstr_w(index) );
1423 return E_NOTIMPL;
1426 static HRESULT WINAPI recordset_get_Index( _Recordset *iface, BSTR *index )
1428 FIXME( "%p, %p\n", iface, index );
1429 return E_NOTIMPL;
1432 static HRESULT WINAPI recordset_Save( _Recordset *iface, VARIANT destination, PersistFormatEnum persist_format )
1434 FIXME( "%p, %s, %u\n", iface, debugstr_variant(&destination), persist_format );
1435 return E_NOTIMPL;
1438 static const struct _RecordsetVtbl recordset_vtbl =
1440 recordset_QueryInterface,
1441 recordset_AddRef,
1442 recordset_Release,
1443 recordset_GetTypeInfoCount,
1444 recordset_GetTypeInfo,
1445 recordset_GetIDsOfNames,
1446 recordset_Invoke,
1447 recordset_get_Properties,
1448 recordset_get_AbsolutePosition,
1449 recordset_put_AbsolutePosition,
1450 recordset_putref_ActiveConnection,
1451 recordset_put_ActiveConnection,
1452 recordset_get_ActiveConnection,
1453 recordset_get_BOF,
1454 recordset_get_Bookmark,
1455 recordset_put_Bookmark,
1456 recordset_get_CacheSize,
1457 recordset_put_CacheSize,
1458 recordset_get_CursorType,
1459 recordset_put_CursorType,
1460 recordset_get_EOF,
1461 recordset_get_Fields,
1462 recordset_get_LockType,
1463 recordset_put_LockType,
1464 recordset_get_MaxRecords,
1465 recordset_put_MaxRecords,
1466 recordset_get_RecordCount,
1467 recordset_putref_Source,
1468 recordset_put_Source,
1469 recordset_get_Source,
1470 recordset_AddNew,
1471 recordset_CancelUpdate,
1472 recordset_Close,
1473 recordset_Delete,
1474 recordset_GetRows,
1475 recordset_Move,
1476 recordset_MoveNext,
1477 recordset_MovePrevious,
1478 recordset_MoveFirst,
1479 recordset_MoveLast,
1480 recordset_Open,
1481 recordset_Requery,
1482 recordset__xResync,
1483 recordset_Update,
1484 recordset_get_AbsolutePage,
1485 recordset_put_AbsolutePage,
1486 recordset_get_EditMode,
1487 recordset_get_Filter,
1488 recordset_put_Filter,
1489 recordset_get_PageCount,
1490 recordset_get_PageSize,
1491 recordset_put_PageSize,
1492 recordset_get_Sort,
1493 recordset_put_Sort,
1494 recordset_get_Status,
1495 recordset_get_State,
1496 recordset__xClone,
1497 recordset_UpdateBatch,
1498 recordset_CancelBatch,
1499 recordset_get_CursorLocation,
1500 recordset_put_CursorLocation,
1501 recordset_NextRecordset,
1502 recordset_Supports,
1503 recordset_get_Collect,
1504 recordset_put_Collect,
1505 recordset_get_MarshalOptions,
1506 recordset_put_MarshalOptions,
1507 recordset_Find,
1508 recordset_Cancel,
1509 recordset_get_DataSource,
1510 recordset_putref_DataSource,
1511 recordset__xSave,
1512 recordset_get_ActiveCommand,
1513 recordset_put_StayInSync,
1514 recordset_get_StayInSync,
1515 recordset_GetString,
1516 recordset_get_DataMember,
1517 recordset_put_DataMember,
1518 recordset_CompareBookmarks,
1519 recordset_Clone,
1520 recordset_Resync,
1521 recordset_Seek,
1522 recordset_put_Index,
1523 recordset_get_Index,
1524 recordset_Save
1527 static inline struct recordset *recordset_from_ISupportErrorInfo( ISupportErrorInfo *iface )
1529 return CONTAINING_RECORD( iface, struct recordset, ISupportErrorInfo_iface );
1532 static HRESULT WINAPI recordset_supporterrorinfo_QueryInterface( ISupportErrorInfo *iface, REFIID riid, void **obj )
1534 struct recordset *recordset = recordset_from_ISupportErrorInfo( iface );
1535 return _Recordset_QueryInterface( &recordset->Recordset_iface, riid, obj );
1538 static ULONG WINAPI recordset_supporterrorinfo_AddRef( ISupportErrorInfo *iface )
1540 struct recordset *recordset = recordset_from_ISupportErrorInfo( iface );
1541 return _Recordset_AddRef( &recordset->Recordset_iface );
1544 static ULONG WINAPI recordset_supporterrorinfo_Release( ISupportErrorInfo *iface )
1546 struct recordset *recordset = recordset_from_ISupportErrorInfo( iface );
1547 return _Recordset_Release( &recordset->Recordset_iface );
1550 static HRESULT WINAPI recordset_supporterrorinfo_InterfaceSupportsErrorInfo( ISupportErrorInfo *iface, REFIID riid )
1552 struct recordset *recordset = recordset_from_ISupportErrorInfo( iface );
1553 FIXME( "%p, %s\n", recordset, debugstr_guid(riid) );
1554 return S_FALSE;
1557 static const ISupportErrorInfoVtbl recordset_supporterrorinfo_vtbl =
1559 recordset_supporterrorinfo_QueryInterface,
1560 recordset_supporterrorinfo_AddRef,
1561 recordset_supporterrorinfo_Release,
1562 recordset_supporterrorinfo_InterfaceSupportsErrorInfo
1565 static HRESULT WINAPI rsconstruction_QueryInterface(ADORecordsetConstruction *iface,
1566 REFIID riid, void **obj)
1568 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
1569 return _Recordset_QueryInterface( &recordset->Recordset_iface, riid, obj );
1572 static ULONG WINAPI rsconstruction_AddRef(ADORecordsetConstruction *iface)
1574 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
1575 return _Recordset_AddRef( &recordset->Recordset_iface );
1578 static ULONG WINAPI rsconstruction_Release(ADORecordsetConstruction *iface)
1580 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
1581 return _Recordset_Release( &recordset->Recordset_iface );
1584 static HRESULT WINAPI rsconstruction_GetTypeInfoCount(ADORecordsetConstruction *iface, UINT *pctinfo)
1586 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
1587 TRACE( "%p, %p\n", recordset, pctinfo );
1588 *pctinfo = 1;
1589 return S_OK;
1592 static HRESULT WINAPI rsconstruction_GetTypeInfo(ADORecordsetConstruction *iface, UINT iTInfo,
1593 LCID lcid, ITypeInfo **ppTInfo)
1595 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
1596 FIXME( "%p %u %u %p\n", recordset, iTInfo, lcid, ppTInfo );
1597 return E_NOTIMPL;
1600 static HRESULT WINAPI rsconstruction_GetIDsOfNames(ADORecordsetConstruction *iface, REFIID riid,
1601 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1603 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
1604 FIXME( "%p %s %p %u %u %p\n", recordset, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId );
1605 return E_NOTIMPL;
1608 static HRESULT WINAPI rsconstruction_Invoke(ADORecordsetConstruction *iface, DISPID dispIdMember,
1609 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
1610 EXCEPINFO *pExcepInfo, UINT *puArgErr)
1612 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
1613 FIXME( "%p %d %s %d %d %p %p %p %p\n", recordset, dispIdMember, debugstr_guid(riid),
1614 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr );
1615 return E_NOTIMPL;
1618 static HRESULT WINAPI rsconstruction_get_Rowset(ADORecordsetConstruction *iface, IUnknown **row_set)
1620 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
1621 HRESULT hr;
1623 TRACE( "%p, %p\n", recordset, row_set );
1625 hr = IRowset_QueryInterface(recordset->row_set, &IID_IUnknown, (void**)row_set);
1626 if ( FAILED(hr) ) return E_FAIL;
1628 return S_OK;
1631 static HRESULT WINAPI rsconstruction_put_Rowset(ADORecordsetConstruction *iface, IUnknown *unk)
1633 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
1634 HRESULT hr;
1635 IRowset *rowset;
1637 TRACE( "%p, %p\n", recordset, unk );
1639 hr = IUnknown_QueryInterface(unk, &IID_IRowset, (void**)&rowset);
1640 if ( FAILED(hr) ) return E_FAIL;
1642 if ( recordset->row_set ) IRowset_Release( recordset->row_set );
1643 recordset->row_set = rowset;
1645 return S_OK;
1648 static HRESULT WINAPI rsconstruction_get_Chapter(ADORecordsetConstruction *iface, LONG *chapter)
1650 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
1651 FIXME( "%p, %p\n", recordset, chapter );
1652 return E_NOTIMPL;
1655 static HRESULT WINAPI rsconstruction_put_Chapter(ADORecordsetConstruction *iface, LONG chapter)
1657 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
1658 FIXME( "%p, %d\n", recordset, chapter );
1659 return E_NOTIMPL;
1662 static HRESULT WINAPI rsconstruction_get_RowPosition(ADORecordsetConstruction *iface, IUnknown **row_pos)
1664 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
1665 FIXME( "%p, %p\n", recordset, row_pos );
1666 return E_NOTIMPL;
1669 static HRESULT WINAPI rsconstruction_put_RowPosition(ADORecordsetConstruction *iface, IUnknown *row_pos)
1671 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
1672 FIXME( "%p, %p\n", recordset, row_pos );
1673 return E_NOTIMPL;
1676 static const ADORecordsetConstructionVtbl rsconstruction_vtbl =
1678 rsconstruction_QueryInterface,
1679 rsconstruction_AddRef,
1680 rsconstruction_Release,
1681 rsconstruction_GetTypeInfoCount,
1682 rsconstruction_GetTypeInfo,
1683 rsconstruction_GetIDsOfNames,
1684 rsconstruction_Invoke,
1685 rsconstruction_get_Rowset,
1686 rsconstruction_put_Rowset,
1687 rsconstruction_get_Chapter,
1688 rsconstruction_put_Chapter,
1689 rsconstruction_get_RowPosition,
1690 rsconstruction_put_RowPosition
1693 HRESULT Recordset_create( void **obj )
1695 struct recordset *recordset;
1697 if (!(recordset = heap_alloc_zero( sizeof(*recordset) ))) return E_OUTOFMEMORY;
1698 recordset->Recordset_iface.lpVtbl = &recordset_vtbl;
1699 recordset->ISupportErrorInfo_iface.lpVtbl = &recordset_supporterrorinfo_vtbl;
1700 recordset->ADORecordsetConstruction_iface.lpVtbl = &rsconstruction_vtbl;
1701 recordset->refs = 1;
1702 recordset->index = -1;
1703 recordset->cursor_location = adUseServer;
1704 recordset->cursor_type = adOpenForwardOnly;
1705 recordset->row_set = NULL;
1707 *obj = &recordset->Recordset_iface;
1708 TRACE( "returning iface %p\n", *obj );
1709 return S_OK;