mfreadwrite/reader: Add missing allocation check (Coverity).
[wine/zf.git] / dlls / msado15 / recordset.c
blob68d4c22d802129c7377467b834bb6af80133224a
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 struct field *field = impl_from_Field( iface );
130 TRACE( "%p, %p\n", field, count );
131 *count = 1;
132 return S_OK;
135 static HRESULT WINAPI field_GetTypeInfo( Field *iface, UINT index, LCID lcid, ITypeInfo **info )
137 struct field *field = impl_from_Field( iface );
138 TRACE( "%p, %u, %u, %p\n", field, index, lcid, info );
139 return get_typeinfo(Field_tid, info);
142 static HRESULT WINAPI field_GetIDsOfNames( Field *iface, REFIID riid, LPOLESTR *names, UINT count,
143 LCID lcid, DISPID *dispid )
145 struct field *field = impl_from_Field( iface );
146 HRESULT hr;
147 ITypeInfo *typeinfo;
149 TRACE( "%p, %s, %p, %u, %u, %p\n", field, debugstr_guid(riid), names, count, lcid, dispid );
151 hr = get_typeinfo(Field_tid, &typeinfo);
152 if(SUCCEEDED(hr))
154 hr = ITypeInfo_GetIDsOfNames(typeinfo, names, count, dispid);
155 ITypeInfo_Release(typeinfo);
158 return hr;
161 static HRESULT WINAPI field_Invoke( Field *iface, DISPID member, REFIID riid, LCID lcid, WORD flags,
162 DISPPARAMS *params, VARIANT *result, EXCEPINFO *excep_info, UINT *arg_err )
164 struct field *field = impl_from_Field( iface );
165 HRESULT hr;
166 ITypeInfo *typeinfo;
168 TRACE( "%p, %d, %s, %d, %d, %p, %p, %p, %p\n", field, member, debugstr_guid(riid), lcid, flags, params,
169 result, excep_info, arg_err );
171 hr = get_typeinfo(Field_tid, &typeinfo);
172 if(SUCCEEDED(hr))
174 hr = ITypeInfo_Invoke(typeinfo, &field->Field_iface, member, flags, params,
175 result, excep_info, arg_err);
176 ITypeInfo_Release(typeinfo);
179 return hr;
182 static HRESULT WINAPI field_get_Properties( Field *iface, Properties **obj )
184 FIXME( "%p, %p\n", iface, obj );
185 return E_NOTIMPL;
188 static HRESULT WINAPI field_get_ActualSize( Field *iface, LONG *size )
190 FIXME( "%p, %p\n", iface, size );
191 return E_NOTIMPL;
194 static HRESULT WINAPI field_get_Attributes( Field *iface, LONG *attrs )
196 struct field *field = impl_from_Field( iface );
198 TRACE( "%p, %p\n", field, attrs );
200 *attrs = field->attrs;
201 return S_OK;
204 static HRESULT WINAPI field_get_DefinedSize( Field *iface, LONG *size )
206 struct field *field = impl_from_Field( iface );
208 TRACE( "%p, %p\n", field, size );
210 *size = field->defined_size;
211 return S_OK;
214 static HRESULT WINAPI field_get_Name( Field *iface, BSTR *str )
216 struct field *field = impl_from_Field( iface );
217 BSTR name;
219 TRACE( "%p, %p\n", field, str );
221 if (!(name = SysAllocString( field->name ))) return E_OUTOFMEMORY;
222 *str = name;
223 return S_OK;
226 static HRESULT WINAPI field_get_Type( Field *iface, DataTypeEnum *type )
228 struct field *field = impl_from_Field( iface );
230 TRACE( "%p, %p\n", field, type );
232 *type = field->type;
233 return S_OK;
236 static LONG get_column_count( struct recordset *recordset )
238 return recordset->fields->count;
241 static HRESULT WINAPI field_get_Value( Field *iface, VARIANT *val )
243 struct field *field = impl_from_Field( iface );
244 ULONG row = field->recordset->index, col = field->index, col_count;
245 VARIANT copy;
246 HRESULT hr;
248 TRACE( "%p, %p\n", field, val );
250 if (field->recordset->state == adStateClosed) return MAKE_ADO_HRESULT( adErrObjectClosed );
251 if (field->recordset->index < 0) return MAKE_ADO_HRESULT( adErrNoCurrentRecord );
253 col_count = get_column_count( field->recordset );
255 VariantInit( &copy );
256 if ((hr = VariantCopy( &copy, &field->recordset->data[row * col_count + col] )) != S_OK) return hr;
258 *val = copy;
259 return S_OK;
262 static HRESULT WINAPI field_put_Value( Field *iface, VARIANT val )
264 struct field *field = impl_from_Field( iface );
265 ULONG row = field->recordset->index, col = field->index, col_count;
266 VARIANT copy;
267 HRESULT hr;
269 TRACE( "%p, %s\n", field, debugstr_variant(&val) );
271 if (field->recordset->state == adStateClosed) return MAKE_ADO_HRESULT( adErrObjectClosed );
272 if (field->recordset->index < 0) return MAKE_ADO_HRESULT( adErrNoCurrentRecord );
274 col_count = get_column_count( field->recordset );
276 VariantInit( &copy );
277 if ((hr = VariantCopy( &copy, &val )) != S_OK) return hr;
279 field->recordset->data[row * col_count + col] = copy;
280 return S_OK;
283 static HRESULT WINAPI field_get_Precision( Field *iface, unsigned char *precision )
285 FIXME( "%p, %p\n", iface, precision );
286 return E_NOTIMPL;
289 static HRESULT WINAPI field_get_NumericScale( Field *iface, unsigned char *scale )
291 FIXME( "%p, %p\n", iface, scale );
292 return E_NOTIMPL;
295 static HRESULT WINAPI field_AppendChunk( Field *iface, VARIANT data )
297 FIXME( "%p, %s\n", iface, debugstr_variant(&data) );
298 return E_NOTIMPL;
301 static HRESULT WINAPI field_GetChunk( Field *iface, LONG length, VARIANT *var )
303 FIXME( "%p, %d, %p\n", iface, length, var );
304 return E_NOTIMPL;
307 static HRESULT WINAPI field_get_OriginalValue( Field *iface, VARIANT *val )
309 FIXME( "%p, %p\n", iface, val );
310 return E_NOTIMPL;
313 static HRESULT WINAPI field_get_UnderlyingValue( Field *iface, VARIANT *val )
315 FIXME( "%p, %p\n", iface, val );
316 return E_NOTIMPL;
319 static HRESULT WINAPI field_get_DataFormat( Field *iface, IUnknown **format )
321 FIXME( "%p, %p\n", iface, format );
322 return E_NOTIMPL;
325 static HRESULT WINAPI field_putref_DataFormat( Field *iface, IUnknown *format )
327 FIXME( "%p, %p\n", iface, format );
328 return E_NOTIMPL;
331 static HRESULT WINAPI field_put_Precision( Field *iface, unsigned char precision )
333 FIXME( "%p, %c\n", iface, precision );
334 return E_NOTIMPL;
337 static HRESULT WINAPI field_put_NumericScale( Field *iface, unsigned char scale )
339 FIXME( "%p, %c\n", iface, scale );
340 return E_NOTIMPL;
343 static HRESULT WINAPI field_put_Type( Field *iface, DataTypeEnum type )
345 struct field *field = impl_from_Field( iface );
347 TRACE( "%p, %u\n", field, type );
349 field->type = type;
350 return S_OK;
353 static HRESULT WINAPI field_put_DefinedSize( Field *iface, LONG size )
355 struct field *field = impl_from_Field( iface );
357 TRACE( "%p, %d\n", field, size );
359 field->defined_size = size;
360 return S_OK;
363 static HRESULT WINAPI field_put_Attributes( Field *iface, LONG attrs )
365 struct field *field = impl_from_Field( iface );
367 TRACE( "%p, %d\n", field, attrs );
369 field->attrs = attrs;
370 return S_OK;
373 static HRESULT WINAPI field_get_Status( Field *iface, LONG *status )
375 FIXME( "%p, %p\n", iface, status );
376 return E_NOTIMPL;
379 static const struct FieldVtbl field_vtbl =
381 field_QueryInterface,
382 field_AddRef,
383 field_Release,
384 field_GetTypeInfoCount,
385 field_GetTypeInfo,
386 field_GetIDsOfNames,
387 field_Invoke,
388 field_get_Properties,
389 field_get_ActualSize,
390 field_get_Attributes,
391 field_get_DefinedSize,
392 field_get_Name,
393 field_get_Type,
394 field_get_Value,
395 field_put_Value,
396 field_get_Precision,
397 field_get_NumericScale,
398 field_AppendChunk,
399 field_GetChunk,
400 field_get_OriginalValue,
401 field_get_UnderlyingValue,
402 field_get_DataFormat,
403 field_putref_DataFormat,
404 field_put_Precision,
405 field_put_NumericScale,
406 field_put_Type,
407 field_put_DefinedSize,
408 field_put_Attributes,
409 field_get_Status
412 static inline struct field *field_from_ISupportErrorInfo( ISupportErrorInfo *iface )
414 return CONTAINING_RECORD( iface, struct field, ISupportErrorInfo_iface );
417 static HRESULT WINAPI field_supporterrorinfo_QueryInterface( ISupportErrorInfo *iface, REFIID riid, void **obj )
419 struct field *field = field_from_ISupportErrorInfo( iface );
420 return Field_QueryInterface( &field->Field_iface, riid, obj );
423 static ULONG WINAPI field_supporterrorinfo_AddRef( ISupportErrorInfo *iface )
425 struct field *field = field_from_ISupportErrorInfo( iface );
426 return Field_AddRef( &field->Field_iface );
429 static ULONG WINAPI field_supporterrorinfo_Release( ISupportErrorInfo *iface )
431 struct field *field = field_from_ISupportErrorInfo( iface );
432 return Field_Release( &field->Field_iface );
435 static HRESULT WINAPI field_supporterrorinfo_InterfaceSupportsErrorInfo( ISupportErrorInfo *iface, REFIID riid )
437 struct field *field = field_from_ISupportErrorInfo( iface );
438 FIXME( "%p, %s\n", field, debugstr_guid(riid) );
439 return S_FALSE;
442 static const ISupportErrorInfoVtbl field_supporterrorinfo_vtbl =
444 field_supporterrorinfo_QueryInterface,
445 field_supporterrorinfo_AddRef,
446 field_supporterrorinfo_Release,
447 field_supporterrorinfo_InterfaceSupportsErrorInfo
450 static HRESULT Field_create( const WCHAR *name, LONG index, struct recordset *recordset, Field **obj )
452 struct field *field;
454 if (!(field = heap_alloc_zero( sizeof(*field) ))) return E_OUTOFMEMORY;
455 field->Field_iface.lpVtbl = &field_vtbl;
456 field->ISupportErrorInfo_iface.lpVtbl = &field_supporterrorinfo_vtbl;
457 if (!(field->name = strdupW( name )))
459 heap_free( field );
460 return E_OUTOFMEMORY;
462 field->index = index;
463 field->recordset = recordset;
465 *obj = &field->Field_iface;
466 TRACE( "returning iface %p\n", *obj );
467 return S_OK;
470 static inline struct fields *impl_from_Fields( Fields *iface )
472 return CONTAINING_RECORD( iface, struct fields, Fields_iface );
475 static ULONG WINAPI fields_AddRef( Fields *iface )
477 struct fields *fields = impl_from_Fields( iface );
478 LONG refs = InterlockedIncrement( &fields->refs );
479 TRACE( "%p new refcount %d\n", fields, refs );
480 return refs;
483 static ULONG WINAPI fields_Release( Fields *iface )
485 struct fields *fields = impl_from_Fields( iface );
486 LONG refs = InterlockedDecrement( &fields->refs );
487 TRACE( "%p new refcount %d\n", fields, refs );
488 if (!refs)
490 if (fields->recordset) _Recordset_Release( &fields->recordset->Recordset_iface );
491 fields->recordset = NULL;
492 WARN( "not destroying %p\n", fields );
493 return InterlockedIncrement( &fields->refs );
495 return refs;
498 static HRESULT WINAPI fields_QueryInterface( Fields *iface, REFIID riid, void **obj )
500 struct fields *fields = impl_from_Fields( iface );
501 TRACE( "%p, %s, %p\n", iface, debugstr_guid(riid), obj );
503 if (IsEqualGUID( riid, &IID_Fields ) || IsEqualGUID( riid, &IID_IDispatch ) ||
504 IsEqualGUID( riid, &IID_IUnknown ))
506 *obj = iface;
508 else if (IsEqualGUID( riid, &IID_ISupportErrorInfo ))
510 *obj = &fields->ISupportErrorInfo_iface;
512 else
514 FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
515 return E_NOINTERFACE;
517 fields_AddRef( iface );
518 return S_OK;
521 static HRESULT WINAPI fields_GetTypeInfoCount( Fields *iface, UINT *count )
523 struct fields *fields = impl_from_Fields( iface );
524 TRACE( "%p, %p\n", fields, count );
525 *count = 1;
526 return S_OK;
529 static HRESULT WINAPI fields_GetTypeInfo( Fields *iface, UINT index, LCID lcid, ITypeInfo **info )
531 struct fields *fields = impl_from_Fields( iface );
532 TRACE( "%p, %u, %u, %p\n", fields, index, lcid, info );
533 return get_typeinfo(Fields_tid, info);
536 static HRESULT WINAPI fields_GetIDsOfNames( Fields *iface, REFIID riid, LPOLESTR *names, UINT count,
537 LCID lcid, DISPID *dispid )
539 struct fields *fields = impl_from_Fields( iface );
540 HRESULT hr;
541 ITypeInfo *typeinfo;
543 TRACE( "%p, %s, %p, %u, %u, %p\n", fields, debugstr_guid(riid), names, count, lcid, dispid );
545 hr = get_typeinfo(Fields_tid, &typeinfo);
546 if(SUCCEEDED(hr))
548 hr = ITypeInfo_GetIDsOfNames(typeinfo, names, count, dispid);
549 ITypeInfo_Release(typeinfo);
552 return hr;
555 static HRESULT WINAPI fields_Invoke( Fields *iface, DISPID member, REFIID riid, LCID lcid, WORD flags,
556 DISPPARAMS *params, VARIANT *result, EXCEPINFO *excep_info, UINT *arg_err )
558 struct fields *fields = impl_from_Fields( iface );
559 HRESULT hr;
560 ITypeInfo *typeinfo;
562 TRACE( "%p, %d, %s, %d, %d, %p, %p, %p, %p\n", fields, member, debugstr_guid(riid), lcid, flags, params,
563 result, excep_info, arg_err );
565 hr = get_typeinfo(Fields_tid, &typeinfo);
566 if(SUCCEEDED(hr))
568 hr = ITypeInfo_Invoke(typeinfo, &fields->Fields_iface, member, flags, params,
569 result, excep_info, arg_err);
570 ITypeInfo_Release(typeinfo);
573 return hr;
576 static HRESULT WINAPI fields_get_Count( Fields *iface, LONG *count )
578 struct fields *fields = impl_from_Fields( iface );
580 TRACE( "%p, %p\n", fields, count );
582 *count = fields->count;
583 return S_OK;
586 static HRESULT WINAPI fields__NewEnum( Fields *iface, IUnknown **obj )
588 FIXME( "%p, %p\n", iface, obj );
589 return E_NOTIMPL;
592 static HRESULT WINAPI fields_Refresh( Fields *iface )
594 FIXME( "%p\n", iface );
595 return E_NOTIMPL;
598 static HRESULT map_index( struct fields *fields, VARIANT *index, ULONG *ret )
600 ULONG i;
602 if (V_VT( index ) != VT_BSTR)
604 FIXME( "variant type %u not supported\n", V_VT( index ) );
605 return E_INVALIDARG;
608 for (i = 0; i < fields->count; i++)
610 BSTR name;
611 BOOL match;
612 HRESULT hr;
614 if ((hr = Field_get_Name( fields->field[i], &name )) != S_OK) return hr;
615 match = !wcsicmp( V_BSTR( index ), name );
616 SysFreeString( name );
617 if (match)
619 *ret = i;
620 return S_OK;
624 return MAKE_ADO_HRESULT(adErrItemNotFound);
627 static HRESULT WINAPI fields_get_Item( Fields *iface, VARIANT index, Field **obj )
629 struct fields *fields = impl_from_Fields( iface );
630 HRESULT hr;
631 ULONG i;
633 TRACE( "%p, %s, %p\n", fields, debugstr_variant(&index), obj );
635 if ((hr = map_index( fields, &index, &i )) != S_OK) return hr;
637 Field_AddRef( fields->field[i] );
638 *obj = fields->field[i];
639 return S_OK;
642 static BOOL resize_fields( struct fields *fields, ULONG count )
644 if (count > fields->allocated)
646 Field **tmp;
647 ULONG new_size = max( count, fields->allocated * 2 );
648 if (!(tmp = heap_realloc( fields->field, new_size * sizeof(*tmp) ))) return FALSE;
649 fields->field = tmp;
650 fields->allocated = new_size;
653 fields->count = count;
654 return TRUE;
657 static HRESULT append_field( struct fields *fields, BSTR name, DataTypeEnum type, LONG size, FieldAttributeEnum attr,
658 VARIANT *value )
660 Field *field;
661 HRESULT hr;
663 if ((hr = Field_create( name, fields->count, fields->recordset, &field )) != S_OK) return hr;
664 Field_put_Type( field, type );
665 Field_put_DefinedSize( field, size );
666 if (attr != adFldUnspecified) Field_put_Attributes( field, attr );
667 if (value) FIXME( "ignoring value %s\n", debugstr_variant(value) );
669 if (!(resize_fields( fields, fields->count + 1 )))
671 Field_Release( field );
672 return E_OUTOFMEMORY;
675 fields->field[fields->count - 1] = field;
676 return S_OK;
679 static HRESULT WINAPI fields__Append( Fields *iface, BSTR name, DataTypeEnum type, LONG size, FieldAttributeEnum attr )
681 struct fields *fields = impl_from_Fields( iface );
683 TRACE( "%p, %s, %u, %d, %d\n", fields, debugstr_w(name), type, size, attr );
685 return append_field( fields, name, type, size, attr, NULL );
688 static HRESULT WINAPI fields_Delete( Fields *iface, VARIANT index )
690 FIXME( "%p, %s\n", iface, debugstr_variant(&index) );
691 return E_NOTIMPL;
694 static HRESULT WINAPI fields_Append( Fields *iface, BSTR name, DataTypeEnum type, LONG size, FieldAttributeEnum attr,
695 VARIANT value )
697 struct fields *fields = impl_from_Fields( iface );
699 TRACE( "%p, %s, %u, %d, %d, %s\n", fields, debugstr_w(name), type, size, attr, debugstr_variant(&value) );
701 return append_field( fields, name, type, size, attr, &value );
704 static HRESULT WINAPI fields_Update( Fields *iface )
706 FIXME( "%p\n", iface );
707 return E_NOTIMPL;
710 static HRESULT WINAPI fields_Resync( Fields *iface, ResyncEnum resync_values )
712 FIXME( "%p, %u\n", iface, resync_values );
713 return E_NOTIMPL;
716 static HRESULT WINAPI fields_CancelUpdate( Fields *iface )
718 FIXME( "%p\n", iface );
719 return E_NOTIMPL;
722 static const struct FieldsVtbl fields_vtbl =
724 fields_QueryInterface,
725 fields_AddRef,
726 fields_Release,
727 fields_GetTypeInfoCount,
728 fields_GetTypeInfo,
729 fields_GetIDsOfNames,
730 fields_Invoke,
731 fields_get_Count,
732 fields__NewEnum,
733 fields_Refresh,
734 fields_get_Item,
735 fields__Append,
736 fields_Delete,
737 fields_Append,
738 fields_Update,
739 fields_Resync,
740 fields_CancelUpdate
743 static inline struct fields *fields_from_ISupportErrorInfo( ISupportErrorInfo *iface )
745 return CONTAINING_RECORD( iface, struct fields, ISupportErrorInfo_iface );
748 static HRESULT WINAPI fields_supporterrorinfo_QueryInterface( ISupportErrorInfo *iface, REFIID riid, void **obj )
750 struct fields *fields = fields_from_ISupportErrorInfo( iface );
751 return Fields_QueryInterface( &fields->Fields_iface, riid, obj );
754 static ULONG WINAPI fields_supporterrorinfo_AddRef( ISupportErrorInfo *iface )
756 struct fields *fields = fields_from_ISupportErrorInfo( iface );
757 return Fields_AddRef( &fields->Fields_iface );
760 static ULONG WINAPI fields_supporterrorinfo_Release( ISupportErrorInfo *iface )
762 struct fields *fields = fields_from_ISupportErrorInfo( iface );
763 return Fields_Release( &fields->Fields_iface );
766 static HRESULT WINAPI fields_supporterrorinfo_InterfaceSupportsErrorInfo( ISupportErrorInfo *iface, REFIID riid )
768 struct fields *fields = fields_from_ISupportErrorInfo( iface );
769 FIXME( "%p, %s\n", fields, debugstr_guid(riid) );
770 return S_FALSE;
773 static const ISupportErrorInfoVtbl fields_supporterrorinfo_vtbl =
775 fields_supporterrorinfo_QueryInterface,
776 fields_supporterrorinfo_AddRef,
777 fields_supporterrorinfo_Release,
778 fields_supporterrorinfo_InterfaceSupportsErrorInfo
781 static void map_rowset_fields(struct recordset *recordset, struct fields *fields)
783 HRESULT hr;
784 IColumnsInfo *columninfo;
785 DBORDINAL columns, i;
786 DBCOLUMNINFO *colinfo;
787 OLECHAR *stringsbuffer;
789 /* Not Finding the interface or GetColumnInfo failing just causes 0 Fields to be returned */
790 hr = IRowset_QueryInterface(recordset->row_set, &IID_IColumnsInfo, (void**)&columninfo);
791 if (FAILED(hr))
792 return;
794 hr = IColumnsInfo_GetColumnInfo(columninfo, &columns, &colinfo, &stringsbuffer);
795 if (SUCCEEDED(hr))
797 for (i=0; i < columns; i++)
799 TRACE("Adding Column %lu, pwszName: %s, pTypeInfo %p, iOrdinal %lu, dwFlags 0x%08x, "
800 "ulColumnSize %lu, wType %d, bPrecision %d, bScale %d\n",
801 i, debugstr_w(colinfo[i].pwszName), colinfo[i].pTypeInfo, colinfo[i].iOrdinal,
802 colinfo[i].dwFlags, colinfo[i].ulColumnSize, colinfo[i].wType,
803 colinfo[i].bPrecision, colinfo[i].bScale);
805 hr = append_field(fields, colinfo[i].pwszName, colinfo[i].wType, colinfo[i].ulColumnSize,
806 colinfo[i].dwFlags, NULL);
807 if (FAILED(hr))
809 ERR("Failed to add Field name - 0x%08x\n", hr);
810 return;
814 CoTaskMemFree(colinfo);
815 CoTaskMemFree(stringsbuffer);
818 IColumnsInfo_Release(columninfo);
821 static HRESULT fields_create( struct recordset *recordset, struct fields **ret )
823 struct fields *fields;
825 if (!(fields = heap_alloc_zero( sizeof(*fields) ))) return E_OUTOFMEMORY;
826 fields->Fields_iface.lpVtbl = &fields_vtbl;
827 fields->ISupportErrorInfo_iface.lpVtbl = &fields_supporterrorinfo_vtbl;
828 fields->refs = 1;
829 fields->recordset = recordset;
830 _Recordset_AddRef( &fields->recordset->Recordset_iface );
832 if ( recordset->row_set )
833 map_rowset_fields(recordset, fields);
835 *ret = fields;
836 TRACE( "returning %p\n", *ret );
837 return S_OK;
840 static inline struct recordset *impl_from_Recordset( _Recordset *iface )
842 return CONTAINING_RECORD( iface, struct recordset, Recordset_iface );
845 static inline struct recordset *impl_from_ADORecordsetConstruction( ADORecordsetConstruction *iface )
847 return CONTAINING_RECORD( iface, struct recordset, ADORecordsetConstruction_iface );
850 static ULONG WINAPI recordset_AddRef( _Recordset *iface )
852 struct recordset *recordset = impl_from_Recordset( iface );
853 LONG refs = InterlockedIncrement( &recordset->refs );
854 TRACE( "%p new refcount %d\n", recordset, refs );
855 return refs;
858 static void close_recordset( struct recordset *recordset )
860 ULONG row, col, col_count;
862 if ( recordset->row_set ) IRowset_Release( recordset->row_set );
863 recordset->row_set = NULL;
865 if (!recordset->fields) return;
866 col_count = get_column_count( recordset );
868 Fields_Release( &recordset->fields->Fields_iface );
869 recordset->fields = NULL;
871 for (row = 0; row < recordset->count; row++)
872 for (col = 0; col < col_count; col++) VariantClear( &recordset->data[row * col_count + col] );
874 recordset->count = recordset->allocated = recordset->index = 0;
875 heap_free( recordset->data );
876 recordset->data = NULL;
879 static ULONG WINAPI recordset_Release( _Recordset *iface )
881 struct recordset *recordset = impl_from_Recordset( iface );
882 LONG refs = InterlockedDecrement( &recordset->refs );
883 TRACE( "%p new refcount %d\n", recordset, refs );
884 if (!refs)
886 TRACE( "destroying %p\n", recordset );
887 close_recordset( recordset );
888 heap_free( recordset );
890 return refs;
893 static HRESULT WINAPI recordset_QueryInterface( _Recordset *iface, REFIID riid, void **obj )
895 struct recordset *recordset = impl_from_Recordset( iface );
896 TRACE( "%p, %s, %p\n", iface, debugstr_guid(riid), obj );
898 *obj = NULL;
900 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch) ||
901 IsEqualIID(riid, &IID__ADO) || IsEqualIID(riid, &IID_Recordset15) ||
902 IsEqualIID(riid, &IID_Recordset20) || IsEqualIID(riid, &IID_Recordset21) ||
903 IsEqualIID(riid, &IID__Recordset))
905 *obj = iface;
907 else if (IsEqualGUID( riid, &IID_ISupportErrorInfo ))
909 *obj = &recordset->ISupportErrorInfo_iface;
911 else if (IsEqualGUID( riid, &IID_ADORecordsetConstruction ))
913 *obj = &recordset->ADORecordsetConstruction_iface;
915 else if (IsEqualGUID( riid, &IID_IRunnableObject ))
917 TRACE("IID_IRunnableObject not supported returning NULL\n");
918 return E_NOINTERFACE;
920 else
922 FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
923 return E_NOINTERFACE;
925 recordset_AddRef( iface );
926 return S_OK;
929 static HRESULT WINAPI recordset_GetTypeInfoCount( _Recordset *iface, UINT *count )
931 struct recordset *recordset = impl_from_Recordset( iface );
932 TRACE( "%p, %p\n", recordset, count );
933 *count = 1;
934 return S_OK;
937 static HRESULT WINAPI recordset_GetTypeInfo( _Recordset *iface, UINT index, LCID lcid, ITypeInfo **info )
939 struct recordset *recordset = impl_from_Recordset( iface );
940 TRACE( "%p, %u, %u, %p\n", recordset, index, lcid, info );
941 return get_typeinfo(Recordset_tid, info);
944 static HRESULT WINAPI recordset_GetIDsOfNames( _Recordset *iface, REFIID riid, LPOLESTR *names, UINT count,
945 LCID lcid, DISPID *dispid )
947 struct recordset *recordset = impl_from_Recordset( iface );
948 HRESULT hr;
949 ITypeInfo *typeinfo;
951 TRACE( "%p, %s, %p, %u, %u, %p\n", recordset, debugstr_guid(riid), names, count, lcid, dispid );
953 hr = get_typeinfo(Recordset_tid, &typeinfo);
954 if(SUCCEEDED(hr))
956 hr = ITypeInfo_GetIDsOfNames(typeinfo, names, count, dispid);
957 ITypeInfo_Release(typeinfo);
960 return hr;
963 static HRESULT WINAPI recordset_Invoke( _Recordset *iface, DISPID member, REFIID riid, LCID lcid, WORD flags,
964 DISPPARAMS *params, VARIANT *result, EXCEPINFO *excep_info, UINT *arg_err )
966 struct recordset *recordset = impl_from_Recordset( iface );
967 HRESULT hr;
968 ITypeInfo *typeinfo;
970 TRACE( "%p, %d, %s, %d, %d, %p, %p, %p, %p\n", recordset, member, debugstr_guid(riid), lcid, flags, params,
971 result, excep_info, arg_err );
973 hr = get_typeinfo(Recordset_tid, &typeinfo);
974 if(SUCCEEDED(hr))
976 hr = ITypeInfo_Invoke(typeinfo, &recordset->Recordset_iface, member, flags, params,
977 result, excep_info, arg_err);
978 ITypeInfo_Release(typeinfo);
981 return hr;
984 static HRESULT WINAPI recordset_get_Properties( _Recordset *iface, Properties **obj )
986 FIXME( "%p, %p\n", iface, obj );
987 return E_NOTIMPL;
990 static HRESULT WINAPI recordset_get_AbsolutePosition( _Recordset *iface, PositionEnum_Param *pos )
992 FIXME( "%p, %p\n", iface, pos );
993 return E_NOTIMPL;
996 static HRESULT WINAPI recordset_put_AbsolutePosition( _Recordset *iface, PositionEnum_Param pos )
998 FIXME( "%p, %d\n", iface, pos );
999 return E_NOTIMPL;
1002 static HRESULT WINAPI recordset_putref_ActiveConnection( _Recordset *iface, IDispatch *connection )
1004 FIXME( "%p, %p\n", iface, connection );
1005 return E_NOTIMPL;
1008 static HRESULT WINAPI recordset_put_ActiveConnection( _Recordset *iface, VARIANT connection )
1010 FIXME( "%p, %s\n", iface, debugstr_variant(&connection) );
1011 return E_NOTIMPL;
1014 static HRESULT WINAPI recordset_get_ActiveConnection( _Recordset *iface, VARIANT *connection )
1016 FIXME( "%p, %p\n", iface, connection );
1017 return E_NOTIMPL;
1020 static HRESULT WINAPI recordset_get_BOF( _Recordset *iface, VARIANT_BOOL *bof )
1022 struct recordset *recordset = impl_from_Recordset( iface );
1024 TRACE( "%p, %p\n", recordset, bof );
1026 *bof = (recordset->index < 0) ? VARIANT_TRUE : VARIANT_FALSE;
1027 return S_OK;
1030 static HRESULT WINAPI recordset_get_Bookmark( _Recordset *iface, VARIANT *bookmark )
1032 struct recordset *recordset = impl_from_Recordset( iface );
1033 TRACE( "%p, %p\n", iface, bookmark );
1035 if (recordset->state == adStateClosed) return MAKE_ADO_HRESULT( adErrObjectClosed );
1036 if (recordset->index < 0) return MAKE_ADO_HRESULT( adErrNoCurrentRecord );
1038 V_VT(bookmark) = VT_I4;
1039 V_I4(bookmark) = recordset->index;
1040 return S_OK;
1043 static HRESULT WINAPI recordset_put_Bookmark( _Recordset *iface, VARIANT bookmark )
1045 struct recordset *recordset = impl_from_Recordset( iface );
1046 TRACE( "%p, %s\n", iface, debugstr_variant(&bookmark) );
1048 if (recordset->state == adStateClosed) return MAKE_ADO_HRESULT( adErrObjectClosed );
1050 if (V_VT(&bookmark) != VT_I4) return MAKE_ADO_HRESULT( adErrInvalidArgument );
1052 recordset->index = V_I4(&bookmark);
1053 return S_OK;
1056 static HRESULT WINAPI recordset_get_CacheSize( _Recordset *iface, LONG *size )
1058 FIXME( "%p, %p\n", iface, size );
1059 return E_NOTIMPL;
1062 static HRESULT WINAPI recordset_put_CacheSize( _Recordset *iface, LONG size )
1064 FIXME( "%p, %d\n", iface, size );
1065 return E_NOTIMPL;
1068 static HRESULT WINAPI recordset_get_CursorType( _Recordset *iface, CursorTypeEnum *cursor_type )
1070 struct recordset *recordset = impl_from_Recordset( iface );
1072 TRACE( "%p, %p\n", iface, cursor_type );
1074 *cursor_type = recordset->cursor_type;
1075 return S_OK;
1078 static HRESULT WINAPI recordset_put_CursorType( _Recordset *iface, CursorTypeEnum cursor_type )
1080 struct recordset *recordset = impl_from_Recordset( iface );
1082 TRACE( "%p, %d\n", iface, cursor_type );
1084 recordset->cursor_type = cursor_type;
1085 return S_OK;
1088 static HRESULT WINAPI recordset_get_EOF( _Recordset *iface, VARIANT_BOOL *eof )
1090 struct recordset *recordset = impl_from_Recordset( iface );
1092 TRACE( "%p, %p\n", recordset, eof );
1094 *eof = (!recordset->count || recordset->index >= recordset->count) ? VARIANT_TRUE : VARIANT_FALSE;
1095 return S_OK;
1098 static HRESULT WINAPI recordset_get_Fields( _Recordset *iface, Fields **obj )
1100 struct recordset *recordset = impl_from_Recordset( iface );
1101 HRESULT hr;
1103 TRACE( "%p, %p\n", recordset, obj );
1105 if (recordset->fields)
1107 /* yes, this adds a reference to the recordset instead of the fields object */
1108 _Recordset_AddRef( &recordset->Recordset_iface );
1109 recordset->fields->recordset = recordset;
1110 *obj = &recordset->fields->Fields_iface;
1111 return S_OK;
1114 if ((hr = fields_create( recordset, &recordset->fields )) != S_OK) return hr;
1116 *obj = &recordset->fields->Fields_iface;
1117 return S_OK;
1120 static HRESULT WINAPI recordset_get_LockType( _Recordset *iface, LockTypeEnum *lock_type )
1122 FIXME( "%p, %p\n", iface, lock_type );
1123 return E_NOTIMPL;
1126 static HRESULT WINAPI recordset_put_LockType( _Recordset *iface, LockTypeEnum lock_type )
1128 FIXME( "%p, %d\n", iface, lock_type );
1129 return E_NOTIMPL;
1132 static HRESULT WINAPI recordset_get_MaxRecords( _Recordset *iface, LONG *max_records )
1134 FIXME( "%p, %p\n", iface, max_records );
1135 return E_NOTIMPL;
1138 static HRESULT WINAPI recordset_put_MaxRecords( _Recordset *iface, LONG max_records )
1140 FIXME( "%p, %d\n", iface, max_records );
1141 return E_NOTIMPL;
1144 static HRESULT WINAPI recordset_get_RecordCount( _Recordset *iface, LONG *count )
1146 struct recordset *recordset = impl_from_Recordset( iface );
1148 TRACE( "%p, %p\n", recordset, count );
1150 *count = recordset->count;
1151 return S_OK;
1154 static HRESULT WINAPI recordset_putref_Source( _Recordset *iface, IDispatch *source )
1156 FIXME( "%p, %p\n", iface, source );
1157 return E_NOTIMPL;
1160 static HRESULT WINAPI recordset_put_Source( _Recordset *iface, BSTR source )
1162 FIXME( "%p, %s\n", iface, debugstr_w(source) );
1163 return E_NOTIMPL;
1166 static HRESULT WINAPI recordset_get_Source( _Recordset *iface, VARIANT *source )
1168 FIXME( "%p, %p\n", iface, source );
1169 return E_NOTIMPL;
1172 static BOOL resize_recordset( struct recordset *recordset, ULONG row_count )
1174 ULONG row_size = get_column_count( recordset ) * sizeof(*recordset->data);
1176 if (row_count > recordset->allocated)
1178 VARIANT *tmp;
1179 ULONG count = max( row_count, recordset->allocated * 2 );
1180 if (!(tmp = heap_realloc_zero( recordset->data, count * row_size ))) return FALSE;
1181 recordset->data = tmp;
1182 recordset->allocated = count;
1185 recordset->count = row_count;
1186 return TRUE;
1189 static HRESULT WINAPI recordset_AddNew( _Recordset *iface, VARIANT field_list, VARIANT values )
1191 struct recordset *recordset = impl_from_Recordset( iface );
1193 TRACE( "%p, %s, %s\n", recordset, debugstr_variant(&field_list), debugstr_variant(&values) );
1194 FIXME( "ignoring field list and values\n" );
1196 if (recordset->state == adStateClosed) return MAKE_ADO_HRESULT( adErrObjectClosed );
1198 if (!resize_recordset( recordset, recordset->count + 1 )) return E_OUTOFMEMORY;
1199 recordset->index++;
1200 return S_OK;
1203 static HRESULT WINAPI recordset_CancelUpdate( _Recordset *iface )
1205 FIXME( "%p\n", iface );
1206 return E_NOTIMPL;
1209 static HRESULT WINAPI recordset_Close( _Recordset *iface )
1211 struct recordset *recordset = impl_from_Recordset( iface );
1213 TRACE( "%p\n", recordset );
1215 if (recordset->state == adStateClosed) return MAKE_ADO_HRESULT( adErrObjectClosed );
1217 close_recordset( recordset );
1218 recordset->state = adStateClosed;
1219 return S_OK;
1222 static HRESULT WINAPI recordset_Delete( _Recordset *iface, AffectEnum affect_records )
1224 FIXME( "%p, %u\n", iface, affect_records );
1225 return E_NOTIMPL;
1228 static HRESULT WINAPI recordset_GetRows( _Recordset *iface, LONG rows, VARIANT start, VARIANT fields, VARIANT *var )
1230 FIXME( "%p, %d, %s, %s, %p\n", iface, rows, debugstr_variant(&start), debugstr_variant(&fields), var );
1231 return E_NOTIMPL;
1234 static HRESULT WINAPI recordset_Move( _Recordset *iface, LONG num_records, VARIANT start )
1236 FIXME( "%p, %d, %s\n", iface, num_records, debugstr_variant(&start) );
1237 return E_NOTIMPL;
1240 static HRESULT WINAPI recordset_MoveNext( _Recordset *iface )
1242 struct recordset *recordset = impl_from_Recordset( iface );
1244 TRACE( "%p\n", recordset );
1246 if (recordset->index < recordset->count) recordset->index++;
1247 return S_OK;
1250 static HRESULT WINAPI recordset_MovePrevious( _Recordset *iface )
1252 struct recordset *recordset = impl_from_Recordset( iface );
1254 TRACE( "%p\n", recordset );
1256 if (recordset->index >= 0) recordset->index--;
1257 return S_OK;
1260 static HRESULT WINAPI recordset_MoveFirst( _Recordset *iface )
1262 struct recordset *recordset = impl_from_Recordset( iface );
1264 TRACE( "%p\n", recordset );
1266 recordset->index = 0;
1267 return S_OK;
1270 static HRESULT WINAPI recordset_MoveLast( _Recordset *iface )
1272 struct recordset *recordset = impl_from_Recordset( iface );
1274 TRACE( "%p\n", recordset );
1276 recordset->index = (recordset->count > 0) ? recordset->count - 1 : 0;
1277 return S_OK;
1280 static HRESULT WINAPI recordset_Open( _Recordset *iface, VARIANT source, VARIANT active_connection,
1281 CursorTypeEnum cursor_type, LockTypeEnum lock_type, LONG options )
1283 struct recordset *recordset = impl_from_Recordset( iface );
1284 ADOConnectionConstruction15 *construct;
1285 IUnknown *session;
1286 ICommandText *command_text;
1287 DBROWCOUNT affected;
1288 IUnknown *rowset;
1289 HRESULT hr;
1291 FIXME( "%p, %s, %s, %d, %d, %d Semi-stub\n", recordset, debugstr_variant(&source), debugstr_variant(&active_connection),
1292 cursor_type, lock_type, options );
1294 if (recordset->state == adStateOpen) return MAKE_ADO_HRESULT( adErrObjectOpen );
1296 if (recordset->fields)
1298 recordset->state = adStateOpen;
1299 return S_OK;
1302 if (V_VT(&active_connection) != VT_DISPATCH)
1304 FIXME("Unsupported Active connection type %d\n", V_VT(&active_connection));
1305 return MAKE_ADO_HRESULT( adErrInvalidConnection );
1308 hr = IDispatch_QueryInterface(V_DISPATCH(&active_connection), &IID_ADOConnectionConstruction15, (void**)&construct);
1309 if (FAILED(hr))
1310 return E_FAIL;
1312 hr = ADOConnectionConstruction15_get_Session(construct, &session);
1313 ADOConnectionConstruction15_Release(construct);
1314 if (FAILED(hr))
1315 return E_FAIL;
1317 if (V_VT(&source) != VT_BSTR)
1319 FIXME("Unsupported source type!\n");
1320 IUnknown_Release(session);
1321 return E_FAIL;
1324 hr = create_command_text(session, V_BSTR(&source), &command_text);
1325 IUnknown_Release(session);
1326 if (FAILED(hr))
1327 return hr;
1329 hr = ICommandText_Execute(command_text, NULL, &IID_IUnknown, NULL, &affected, &rowset);
1330 ICommandText_Release(command_text);
1331 if (FAILED(hr))
1332 return hr;
1334 ADORecordsetConstruction_put_Rowset(&recordset->ADORecordsetConstruction_iface, rowset);
1335 recordset->cursor_type = cursor_type;
1336 recordset->state = adStateOpen;
1338 IUnknown_Release(rowset);
1340 return hr;
1343 static HRESULT WINAPI recordset_Requery( _Recordset *iface, LONG options )
1345 FIXME( "%p, %d\n", iface, options );
1346 return E_NOTIMPL;
1349 static HRESULT WINAPI recordset__xResync( _Recordset *iface, AffectEnum affect_records )
1351 FIXME( "%p, %u\n", iface, affect_records );
1352 return E_NOTIMPL;
1355 static HRESULT WINAPI recordset_Update( _Recordset *iface, VARIANT fields, VARIANT values )
1357 FIXME( "%p, %s, %s\n", iface, debugstr_variant(&fields), debugstr_variant(&values) );
1358 return E_NOTIMPL;
1361 static HRESULT WINAPI recordset_get_AbsolutePage( _Recordset *iface, PositionEnum_Param *pos )
1363 FIXME( "%p, %p\n", iface, pos );
1364 return E_NOTIMPL;
1367 static HRESULT WINAPI recordset_put_AbsolutePage( _Recordset *iface, PositionEnum_Param pos )
1369 FIXME( "%p, %d\n", iface, pos );
1370 return E_NOTIMPL;
1373 static HRESULT WINAPI recordset_get_EditMode( _Recordset *iface, EditModeEnum *mode )
1375 FIXME( "%p, %p\n", iface, mode );
1376 return E_NOTIMPL;
1379 static HRESULT WINAPI recordset_get_Filter( _Recordset *iface, VARIANT *criteria )
1381 FIXME( "%p, %p\n", iface, criteria );
1382 return E_NOTIMPL;
1385 static HRESULT WINAPI recordset_put_Filter( _Recordset *iface, VARIANT criteria )
1387 FIXME( "%p, %s\n", iface, debugstr_variant(&criteria) );
1388 return E_NOTIMPL;
1391 static HRESULT WINAPI recordset_get_PageCount( _Recordset *iface, LONG *count )
1393 FIXME( "%p, %p\n", iface, count );
1394 return E_NOTIMPL;
1397 static HRESULT WINAPI recordset_get_PageSize( _Recordset *iface, LONG *size )
1399 FIXME( "%p, %p\n", iface, size );
1400 return E_NOTIMPL;
1403 static HRESULT WINAPI recordset_put_PageSize( _Recordset *iface, LONG size )
1405 FIXME( "%p, %d\n", iface, size );
1406 return E_NOTIMPL;
1409 static HRESULT WINAPI recordset_get_Sort( _Recordset *iface, BSTR *criteria )
1411 FIXME( "%p, %p\n", iface, criteria );
1412 return E_NOTIMPL;
1415 static HRESULT WINAPI recordset_put_Sort( _Recordset *iface, BSTR criteria )
1417 FIXME( "%p, %s\n", iface, debugstr_w(criteria) );
1418 return E_NOTIMPL;
1421 static HRESULT WINAPI recordset_get_Status( _Recordset *iface, LONG *status )
1423 FIXME( "%p, %p\n", iface, status );
1424 return E_NOTIMPL;
1427 static HRESULT WINAPI recordset_get_State( _Recordset *iface, LONG *state )
1429 struct recordset *recordset = impl_from_Recordset( iface );
1431 TRACE( "%p, %p\n", recordset, state );
1433 *state = recordset->state;
1434 return S_OK;
1437 static HRESULT WINAPI recordset__xClone( _Recordset *iface, _Recordset **obj )
1439 FIXME( "%p, %p\n", iface, obj );
1440 return E_NOTIMPL;
1443 static HRESULT WINAPI recordset_UpdateBatch( _Recordset *iface, AffectEnum affect_records )
1445 FIXME( "%p, %u\n", iface, affect_records );
1446 return E_NOTIMPL;
1449 static HRESULT WINAPI recordset_CancelBatch( _Recordset *iface, AffectEnum affect_records )
1451 FIXME( "%p, %u\n", iface, affect_records );
1452 return E_NOTIMPL;
1455 static HRESULT WINAPI recordset_get_CursorLocation( _Recordset *iface, CursorLocationEnum *cursor_loc )
1457 struct recordset *recordset = impl_from_Recordset( iface );
1459 TRACE( "%p, %p\n", iface, cursor_loc );
1461 *cursor_loc = recordset->cursor_location;
1463 return S_OK;
1466 static HRESULT WINAPI recordset_put_CursorLocation( _Recordset *iface, CursorLocationEnum cursor_loc )
1468 struct recordset *recordset = impl_from_Recordset( iface );
1470 TRACE( "%p, %u\n", iface, cursor_loc );
1472 if (recordset->state == adStateOpen) return MAKE_ADO_HRESULT( adErrObjectOpen );
1474 recordset->cursor_location = cursor_loc;
1476 return S_OK;
1479 static HRESULT WINAPI recordset_NextRecordset( _Recordset *iface, VARIANT *records_affected, _Recordset **record_set )
1481 FIXME( "%p, %p, %p\n", iface, records_affected, record_set );
1482 return E_NOTIMPL;
1485 static HRESULT WINAPI recordset_Supports( _Recordset *iface, CursorOptionEnum cursor_options, VARIANT_BOOL *ret )
1487 FIXME( "%p, %08x, %p\n", iface, cursor_options, ret );
1488 return E_NOTIMPL;
1491 static HRESULT WINAPI recordset_get_Collect( _Recordset *iface, VARIANT index, VARIANT *var )
1493 FIXME( "%p, %s, %p\n", iface, debugstr_variant(&index), var );
1494 return E_NOTIMPL;
1497 static HRESULT WINAPI recordset_put_Collect( _Recordset *iface, VARIANT index, VARIANT var )
1499 FIXME( "%p, %s, %s\n", iface, debugstr_variant(&index), debugstr_variant(&var) );
1500 return E_NOTIMPL;
1503 static HRESULT WINAPI recordset_get_MarshalOptions( _Recordset *iface, MarshalOptionsEnum *options )
1505 FIXME( "%p, %p\n", iface, options );
1506 return E_NOTIMPL;
1509 static HRESULT WINAPI recordset_put_MarshalOptions( _Recordset *iface, MarshalOptionsEnum options )
1511 FIXME( "%p, %u\n", iface, options );
1512 return E_NOTIMPL;
1515 static HRESULT WINAPI recordset_Find( _Recordset *iface, BSTR criteria, LONG skip_records,
1516 SearchDirectionEnum search_direction, VARIANT start )
1518 FIXME( "%p, %s, %d, %d, %s\n", iface, debugstr_w(criteria), skip_records, search_direction,
1519 debugstr_variant(&start) );
1520 return E_NOTIMPL;
1523 static HRESULT WINAPI recordset_Cancel( _Recordset *iface )
1525 FIXME( "%p\n", iface );
1526 return E_NOTIMPL;
1529 static HRESULT WINAPI recordset_get_DataSource( _Recordset *iface, IUnknown **data_source )
1531 FIXME( "%p, %p\n", iface, data_source );
1532 return E_NOTIMPL;
1535 static HRESULT WINAPI recordset_putref_DataSource( _Recordset *iface, IUnknown *data_source )
1537 FIXME( "%p, %p\n", iface, data_source );
1538 return E_NOTIMPL;
1541 static HRESULT WINAPI recordset__xSave( _Recordset *iface, BSTR filename, PersistFormatEnum persist_format )
1543 FIXME( "%p, %s, %u\n", iface, debugstr_w(filename), persist_format );
1544 return E_NOTIMPL;
1547 static HRESULT WINAPI recordset_get_ActiveCommand( _Recordset *iface, IDispatch **cmd )
1549 FIXME( "%p, %p\n", iface, cmd );
1550 return E_NOTIMPL;
1553 static HRESULT WINAPI recordset_put_StayInSync( _Recordset *iface, VARIANT_BOOL stay_in_sync )
1555 FIXME( "%p, %d\n", iface, stay_in_sync );
1556 return E_NOTIMPL;
1559 static HRESULT WINAPI recordset_get_StayInSync( _Recordset *iface, VARIANT_BOOL *stay_in_sync )
1561 FIXME( "%p, %p\n", iface, stay_in_sync );
1562 return E_NOTIMPL;
1565 static HRESULT WINAPI recordset_GetString( _Recordset *iface, StringFormatEnum string_format, LONG num_rows,
1566 BSTR column_delimiter, BSTR row_delimiter, BSTR null_expr,
1567 BSTR *ret_string )
1569 FIXME( "%p, %u, %d, %s, %s, %s, %p\n", iface, string_format, num_rows, debugstr_w(column_delimiter),
1570 debugstr_w(row_delimiter), debugstr_w(null_expr), ret_string );
1571 return E_NOTIMPL;
1574 static HRESULT WINAPI recordset_get_DataMember( _Recordset *iface, BSTR *data_member )
1576 FIXME( "%p, %p\n", iface, data_member );
1577 return E_NOTIMPL;
1580 static HRESULT WINAPI recordset_put_DataMember( _Recordset *iface, BSTR data_member )
1582 FIXME( "%p, %s\n", iface, debugstr_w(data_member) );
1583 return E_NOTIMPL;
1586 static HRESULT WINAPI recordset_CompareBookmarks( _Recordset *iface, VARIANT bookmark1, VARIANT bookmark2, CompareEnum *compare )
1588 FIXME( "%p, %s, %s, %p\n", iface, debugstr_variant(&bookmark1), debugstr_variant(&bookmark2), compare );
1589 return E_NOTIMPL;
1592 static HRESULT WINAPI recordset_Clone( _Recordset *iface, LockTypeEnum lock_type, _Recordset **obj )
1594 FIXME( "%p, %d, %p\n", iface, lock_type, obj );
1595 return E_NOTIMPL;
1598 static HRESULT WINAPI recordset_Resync( _Recordset *iface, AffectEnum affect_records, ResyncEnum resync_values )
1600 FIXME( "%p, %u, %u\n", iface, affect_records, resync_values );
1601 return E_NOTIMPL;
1604 static HRESULT WINAPI recordset_Seek( _Recordset *iface, VARIANT key_values, SeekEnum seek_option )
1606 FIXME( "%p, %s, %u\n", iface, debugstr_variant(&key_values), seek_option );
1607 return E_NOTIMPL;
1610 static HRESULT WINAPI recordset_put_Index( _Recordset *iface, BSTR index )
1612 FIXME( "%p, %s\n", iface, debugstr_w(index) );
1613 return E_NOTIMPL;
1616 static HRESULT WINAPI recordset_get_Index( _Recordset *iface, BSTR *index )
1618 FIXME( "%p, %p\n", iface, index );
1619 return E_NOTIMPL;
1622 static HRESULT WINAPI recordset_Save( _Recordset *iface, VARIANT destination, PersistFormatEnum persist_format )
1624 FIXME( "%p, %s, %u\n", iface, debugstr_variant(&destination), persist_format );
1625 return E_NOTIMPL;
1628 static const struct _RecordsetVtbl recordset_vtbl =
1630 recordset_QueryInterface,
1631 recordset_AddRef,
1632 recordset_Release,
1633 recordset_GetTypeInfoCount,
1634 recordset_GetTypeInfo,
1635 recordset_GetIDsOfNames,
1636 recordset_Invoke,
1637 recordset_get_Properties,
1638 recordset_get_AbsolutePosition,
1639 recordset_put_AbsolutePosition,
1640 recordset_putref_ActiveConnection,
1641 recordset_put_ActiveConnection,
1642 recordset_get_ActiveConnection,
1643 recordset_get_BOF,
1644 recordset_get_Bookmark,
1645 recordset_put_Bookmark,
1646 recordset_get_CacheSize,
1647 recordset_put_CacheSize,
1648 recordset_get_CursorType,
1649 recordset_put_CursorType,
1650 recordset_get_EOF,
1651 recordset_get_Fields,
1652 recordset_get_LockType,
1653 recordset_put_LockType,
1654 recordset_get_MaxRecords,
1655 recordset_put_MaxRecords,
1656 recordset_get_RecordCount,
1657 recordset_putref_Source,
1658 recordset_put_Source,
1659 recordset_get_Source,
1660 recordset_AddNew,
1661 recordset_CancelUpdate,
1662 recordset_Close,
1663 recordset_Delete,
1664 recordset_GetRows,
1665 recordset_Move,
1666 recordset_MoveNext,
1667 recordset_MovePrevious,
1668 recordset_MoveFirst,
1669 recordset_MoveLast,
1670 recordset_Open,
1671 recordset_Requery,
1672 recordset__xResync,
1673 recordset_Update,
1674 recordset_get_AbsolutePage,
1675 recordset_put_AbsolutePage,
1676 recordset_get_EditMode,
1677 recordset_get_Filter,
1678 recordset_put_Filter,
1679 recordset_get_PageCount,
1680 recordset_get_PageSize,
1681 recordset_put_PageSize,
1682 recordset_get_Sort,
1683 recordset_put_Sort,
1684 recordset_get_Status,
1685 recordset_get_State,
1686 recordset__xClone,
1687 recordset_UpdateBatch,
1688 recordset_CancelBatch,
1689 recordset_get_CursorLocation,
1690 recordset_put_CursorLocation,
1691 recordset_NextRecordset,
1692 recordset_Supports,
1693 recordset_get_Collect,
1694 recordset_put_Collect,
1695 recordset_get_MarshalOptions,
1696 recordset_put_MarshalOptions,
1697 recordset_Find,
1698 recordset_Cancel,
1699 recordset_get_DataSource,
1700 recordset_putref_DataSource,
1701 recordset__xSave,
1702 recordset_get_ActiveCommand,
1703 recordset_put_StayInSync,
1704 recordset_get_StayInSync,
1705 recordset_GetString,
1706 recordset_get_DataMember,
1707 recordset_put_DataMember,
1708 recordset_CompareBookmarks,
1709 recordset_Clone,
1710 recordset_Resync,
1711 recordset_Seek,
1712 recordset_put_Index,
1713 recordset_get_Index,
1714 recordset_Save
1717 static inline struct recordset *recordset_from_ISupportErrorInfo( ISupportErrorInfo *iface )
1719 return CONTAINING_RECORD( iface, struct recordset, ISupportErrorInfo_iface );
1722 static HRESULT WINAPI recordset_supporterrorinfo_QueryInterface( ISupportErrorInfo *iface, REFIID riid, void **obj )
1724 struct recordset *recordset = recordset_from_ISupportErrorInfo( iface );
1725 return _Recordset_QueryInterface( &recordset->Recordset_iface, riid, obj );
1728 static ULONG WINAPI recordset_supporterrorinfo_AddRef( ISupportErrorInfo *iface )
1730 struct recordset *recordset = recordset_from_ISupportErrorInfo( iface );
1731 return _Recordset_AddRef( &recordset->Recordset_iface );
1734 static ULONG WINAPI recordset_supporterrorinfo_Release( ISupportErrorInfo *iface )
1736 struct recordset *recordset = recordset_from_ISupportErrorInfo( iface );
1737 return _Recordset_Release( &recordset->Recordset_iface );
1740 static HRESULT WINAPI recordset_supporterrorinfo_InterfaceSupportsErrorInfo( ISupportErrorInfo *iface, REFIID riid )
1742 struct recordset *recordset = recordset_from_ISupportErrorInfo( iface );
1743 FIXME( "%p, %s\n", recordset, debugstr_guid(riid) );
1744 return S_FALSE;
1747 static const ISupportErrorInfoVtbl recordset_supporterrorinfo_vtbl =
1749 recordset_supporterrorinfo_QueryInterface,
1750 recordset_supporterrorinfo_AddRef,
1751 recordset_supporterrorinfo_Release,
1752 recordset_supporterrorinfo_InterfaceSupportsErrorInfo
1755 static HRESULT WINAPI rsconstruction_QueryInterface(ADORecordsetConstruction *iface,
1756 REFIID riid, void **obj)
1758 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
1759 return _Recordset_QueryInterface( &recordset->Recordset_iface, riid, obj );
1762 static ULONG WINAPI rsconstruction_AddRef(ADORecordsetConstruction *iface)
1764 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
1765 return _Recordset_AddRef( &recordset->Recordset_iface );
1768 static ULONG WINAPI rsconstruction_Release(ADORecordsetConstruction *iface)
1770 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
1771 return _Recordset_Release( &recordset->Recordset_iface );
1774 static HRESULT WINAPI rsconstruction_GetTypeInfoCount(ADORecordsetConstruction *iface, UINT *pctinfo)
1776 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
1777 TRACE( "%p, %p\n", recordset, pctinfo );
1778 *pctinfo = 1;
1779 return S_OK;
1782 static HRESULT WINAPI rsconstruction_GetTypeInfo(ADORecordsetConstruction *iface, UINT iTInfo,
1783 LCID lcid, ITypeInfo **ppTInfo)
1785 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
1786 TRACE( "%p %u %u %p\n", recordset, iTInfo, lcid, ppTInfo );
1787 return get_typeinfo(ADORecordsetConstruction_tid, ppTInfo);
1790 static HRESULT WINAPI rsconstruction_GetIDsOfNames(ADORecordsetConstruction *iface, REFIID riid,
1791 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1793 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
1794 HRESULT hr;
1795 ITypeInfo *typeinfo;
1797 TRACE( "%p %s %p %u %u %p\n", recordset, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId );
1799 hr = get_typeinfo(ADORecordsetConstruction_tid, &typeinfo);
1800 if(SUCCEEDED(hr))
1802 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1803 ITypeInfo_Release(typeinfo);
1806 return hr;
1809 static HRESULT WINAPI rsconstruction_Invoke(ADORecordsetConstruction *iface, DISPID dispIdMember,
1810 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
1811 EXCEPINFO *pExcepInfo, UINT *puArgErr)
1813 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
1814 HRESULT hr;
1815 ITypeInfo *typeinfo;
1817 TRACE( "%p %d %s %d %d %p %p %p %p\n", recordset, dispIdMember, debugstr_guid(riid),
1818 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr );
1820 hr = get_typeinfo(ADORecordsetConstruction_tid, &typeinfo);
1821 if(SUCCEEDED(hr))
1823 hr = ITypeInfo_Invoke(typeinfo, &recordset->ADORecordsetConstruction_iface, dispIdMember, wFlags,
1824 pDispParams, pVarResult, pExcepInfo, puArgErr);
1825 ITypeInfo_Release(typeinfo);
1828 return hr;
1831 static HRESULT WINAPI rsconstruction_get_Rowset(ADORecordsetConstruction *iface, IUnknown **row_set)
1833 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
1834 HRESULT hr;
1836 TRACE( "%p, %p\n", recordset, row_set );
1838 hr = IRowset_QueryInterface(recordset->row_set, &IID_IUnknown, (void**)row_set);
1839 if ( FAILED(hr) ) return E_FAIL;
1841 return S_OK;
1844 static HRESULT WINAPI rsconstruction_put_Rowset(ADORecordsetConstruction *iface, IUnknown *unk)
1846 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
1847 HRESULT hr;
1848 IRowset *rowset;
1850 TRACE( "%p, %p\n", recordset, unk );
1852 hr = IUnknown_QueryInterface(unk, &IID_IRowset, (void**)&rowset);
1853 if ( FAILED(hr) ) return E_FAIL;
1855 if ( recordset->row_set ) IRowset_Release( recordset->row_set );
1856 recordset->row_set = rowset;
1858 return S_OK;
1861 static HRESULT WINAPI rsconstruction_get_Chapter(ADORecordsetConstruction *iface, LONG *chapter)
1863 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
1864 FIXME( "%p, %p\n", recordset, chapter );
1865 return E_NOTIMPL;
1868 static HRESULT WINAPI rsconstruction_put_Chapter(ADORecordsetConstruction *iface, LONG chapter)
1870 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
1871 FIXME( "%p, %d\n", recordset, chapter );
1872 return E_NOTIMPL;
1875 static HRESULT WINAPI rsconstruction_get_RowPosition(ADORecordsetConstruction *iface, IUnknown **row_pos)
1877 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
1878 FIXME( "%p, %p\n", recordset, row_pos );
1879 return E_NOTIMPL;
1882 static HRESULT WINAPI rsconstruction_put_RowPosition(ADORecordsetConstruction *iface, IUnknown *row_pos)
1884 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
1885 FIXME( "%p, %p\n", recordset, row_pos );
1886 return E_NOTIMPL;
1889 static const ADORecordsetConstructionVtbl rsconstruction_vtbl =
1891 rsconstruction_QueryInterface,
1892 rsconstruction_AddRef,
1893 rsconstruction_Release,
1894 rsconstruction_GetTypeInfoCount,
1895 rsconstruction_GetTypeInfo,
1896 rsconstruction_GetIDsOfNames,
1897 rsconstruction_Invoke,
1898 rsconstruction_get_Rowset,
1899 rsconstruction_put_Rowset,
1900 rsconstruction_get_Chapter,
1901 rsconstruction_put_Chapter,
1902 rsconstruction_get_RowPosition,
1903 rsconstruction_put_RowPosition
1906 HRESULT Recordset_create( void **obj )
1908 struct recordset *recordset;
1910 if (!(recordset = heap_alloc_zero( sizeof(*recordset) ))) return E_OUTOFMEMORY;
1911 recordset->Recordset_iface.lpVtbl = &recordset_vtbl;
1912 recordset->ISupportErrorInfo_iface.lpVtbl = &recordset_supporterrorinfo_vtbl;
1913 recordset->ADORecordsetConstruction_iface.lpVtbl = &rsconstruction_vtbl;
1914 recordset->refs = 1;
1915 recordset->index = -1;
1916 recordset->cursor_location = adUseServer;
1917 recordset->cursor_type = adOpenForwardOnly;
1918 recordset->row_set = NULL;
1920 *obj = &recordset->Recordset_iface;
1921 TRACE( "returning iface %p\n", *obj );
1922 return S_OK;