msado15: Semi-stub _Recordset get/put Filter.
[wine.git] / dlls / msado15 / recordset.c
blobea5c233f95a4448ec642a4d62abb023e0d2de528
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"
30 #include "msado15_private.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(msado15);
34 struct fields;
35 struct recordset
37 _Recordset Recordset_iface;
38 ADORecordsetConstruction ADORecordsetConstruction_iface;
39 ISupportErrorInfo ISupportErrorInfo_iface;
40 LONG refs;
41 LONG state;
42 struct fields *fields;
43 LONG count;
44 LONG allocated;
45 LONG index;
46 VARIANT *data;
47 CursorLocationEnum cursor_location;
48 CursorTypeEnum cursor_type;
49 IRowset *row_set;
50 EditModeEnum editmode;
51 VARIANT filter;
54 struct fields
56 Fields Fields_iface;
57 ISupportErrorInfo ISupportErrorInfo_iface;
58 LONG refs;
59 Field **field;
60 ULONG count;
61 ULONG allocated;
62 struct recordset *recordset;
65 struct field
67 Field Field_iface;
68 ISupportErrorInfo ISupportErrorInfo_iface;
69 Properties Properties_iface;
70 LONG refs;
71 WCHAR *name;
72 DataTypeEnum type;
73 LONG defined_size;
74 LONG attrs;
75 LONG index;
76 struct recordset *recordset;
79 static inline struct field *impl_from_Field( Field *iface )
81 return CONTAINING_RECORD( iface, struct field, Field_iface );
84 static inline struct field *impl_from_Properties( Properties *iface )
86 return CONTAINING_RECORD( iface, struct field, Properties_iface );
89 static ULONG WINAPI field_AddRef( Field *iface )
91 struct field *field = impl_from_Field( iface );
92 LONG refs = InterlockedIncrement( &field->refs );
93 TRACE( "%p new refcount %ld\n", field, refs );
94 return refs;
97 static ULONG WINAPI field_Release( Field *iface )
99 struct field *field = impl_from_Field( iface );
100 LONG refs = InterlockedDecrement( &field->refs );
101 TRACE( "%p new refcount %ld\n", field, refs );
102 if (!refs)
104 TRACE( "destroying %p\n", field );
105 free( field->name );
106 free( field );
108 return refs;
111 static HRESULT WINAPI field_QueryInterface( Field *iface, REFIID riid, void **obj )
113 struct field *field = impl_from_Field( iface );
114 TRACE( "%p, %s, %p\n", iface, debugstr_guid(riid), obj );
116 if (IsEqualGUID( riid, &IID_Field ) || IsEqualGUID( riid, &IID_IDispatch ) ||
117 IsEqualGUID( riid, &IID_IUnknown ))
119 *obj = iface;
121 else if (IsEqualGUID( riid, &IID_ISupportErrorInfo ))
123 *obj = &field->ISupportErrorInfo_iface;
125 else
127 FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
128 return E_NOINTERFACE;
130 field_AddRef( iface );
131 return S_OK;
134 static HRESULT WINAPI field_GetTypeInfoCount( Field *iface, UINT *count )
136 struct field *field = impl_from_Field( iface );
137 TRACE( "%p, %p\n", field, count );
138 *count = 1;
139 return S_OK;
142 static HRESULT WINAPI field_GetTypeInfo( Field *iface, UINT index, LCID lcid, ITypeInfo **info )
144 struct field *field = impl_from_Field( iface );
145 TRACE( "%p, %u, %lu, %p\n", field, index, lcid, info );
146 return get_typeinfo(Field_tid, info);
149 static HRESULT WINAPI field_GetIDsOfNames( Field *iface, REFIID riid, LPOLESTR *names, UINT count,
150 LCID lcid, DISPID *dispid )
152 struct field *field = impl_from_Field( iface );
153 HRESULT hr;
154 ITypeInfo *typeinfo;
156 TRACE( "%p, %s, %p, %u, %lu, %p\n", field, debugstr_guid(riid), names, count, lcid, dispid );
158 hr = get_typeinfo(Field_tid, &typeinfo);
159 if(SUCCEEDED(hr))
161 hr = ITypeInfo_GetIDsOfNames(typeinfo, names, count, dispid);
162 ITypeInfo_Release(typeinfo);
165 return hr;
168 static HRESULT WINAPI field_Invoke( Field *iface, DISPID member, REFIID riid, LCID lcid, WORD flags,
169 DISPPARAMS *params, VARIANT *result, EXCEPINFO *excep_info, UINT *arg_err )
171 struct field *field = impl_from_Field( iface );
172 HRESULT hr;
173 ITypeInfo *typeinfo;
175 TRACE( "%p, %ld, %s, %ld, %d, %p, %p, %p, %p\n", field, member, debugstr_guid(riid), lcid, flags, params,
176 result, excep_info, arg_err );
178 hr = get_typeinfo(Field_tid, &typeinfo);
179 if(SUCCEEDED(hr))
181 hr = ITypeInfo_Invoke(typeinfo, &field->Field_iface, member, flags, params,
182 result, excep_info, arg_err);
183 ITypeInfo_Release(typeinfo);
186 return hr;
189 static HRESULT WINAPI field_get_Properties( Field *iface, Properties **obj )
191 struct field *field = impl_from_Field( iface );
192 TRACE( "%p, %p\n", iface, obj );
194 *obj = &field->Properties_iface;
195 Properties_AddRef(&field->Properties_iface);
196 return S_OK;
199 static HRESULT WINAPI field_get_ActualSize( Field *iface, ADO_LONGPTR *size )
201 FIXME( "%p, %p\n", iface, size );
202 return E_NOTIMPL;
205 static HRESULT WINAPI field_get_Attributes( Field *iface, LONG *attrs )
207 struct field *field = impl_from_Field( iface );
209 TRACE( "%p, %p\n", field, attrs );
211 *attrs = field->attrs;
212 return S_OK;
215 static HRESULT WINAPI field_get_DefinedSize( Field *iface, ADO_LONGPTR *size )
217 struct field *field = impl_from_Field( iface );
219 TRACE( "%p, %p\n", field, size );
221 *size = field->defined_size;
222 return S_OK;
225 static HRESULT WINAPI field_get_Name( Field *iface, BSTR *str )
227 struct field *field = impl_from_Field( iface );
228 BSTR name;
230 TRACE( "%p, %p\n", field, str );
232 if (!(name = SysAllocString( field->name ))) return E_OUTOFMEMORY;
233 *str = name;
234 return S_OK;
237 static HRESULT WINAPI field_get_Type( Field *iface, DataTypeEnum *type )
239 struct field *field = impl_from_Field( iface );
241 TRACE( "%p, %p\n", field, type );
243 *type = field->type;
244 return S_OK;
247 static LONG get_column_count( struct recordset *recordset )
249 return recordset->fields->count;
252 static HRESULT WINAPI field_get_Value( Field *iface, VARIANT *val )
254 struct field *field = impl_from_Field( iface );
255 ULONG row = field->recordset->index, col = field->index, col_count;
256 VARIANT copy;
257 HRESULT hr;
259 TRACE( "%p, %p\n", field, val );
261 if (field->recordset->state == adStateClosed) return MAKE_ADO_HRESULT( adErrObjectClosed );
262 if (field->recordset->index < 0) return MAKE_ADO_HRESULT( adErrNoCurrentRecord );
264 col_count = get_column_count( field->recordset );
266 VariantInit( &copy );
267 if ((hr = VariantCopy( &copy, &field->recordset->data[row * col_count + col] )) != S_OK) return hr;
269 *val = copy;
270 return S_OK;
273 static HRESULT WINAPI field_put_Value( Field *iface, VARIANT val )
275 struct field *field = impl_from_Field( iface );
276 ULONG row = field->recordset->index, col = field->index, col_count;
277 VARIANT copy;
278 HRESULT hr;
280 TRACE( "%p, %s\n", field, debugstr_variant(&val) );
282 if (field->recordset->state == adStateClosed) return MAKE_ADO_HRESULT( adErrObjectClosed );
283 if (field->recordset->index < 0) return MAKE_ADO_HRESULT( adErrNoCurrentRecord );
285 col_count = get_column_count( field->recordset );
287 VariantInit( &copy );
288 if ((hr = VariantCopy( &copy, &val )) != S_OK) return hr;
290 field->recordset->data[row * col_count + col] = copy;
291 return S_OK;
294 static HRESULT WINAPI field_get_Precision( Field *iface, unsigned char *precision )
296 FIXME( "%p, %p\n", iface, precision );
297 return E_NOTIMPL;
300 static HRESULT WINAPI field_get_NumericScale( Field *iface, unsigned char *scale )
302 FIXME( "%p, %p\n", iface, scale );
303 return E_NOTIMPL;
306 static HRESULT WINAPI field_AppendChunk( Field *iface, VARIANT data )
308 FIXME( "%p, %s\n", iface, debugstr_variant(&data) );
309 return E_NOTIMPL;
312 static HRESULT WINAPI field_GetChunk( Field *iface, LONG length, VARIANT *var )
314 FIXME( "%p, %ld, %p\n", iface, length, var );
315 return E_NOTIMPL;
318 static HRESULT WINAPI field_get_OriginalValue( Field *iface, VARIANT *val )
320 FIXME( "%p, %p\n", iface, val );
321 return E_NOTIMPL;
324 static HRESULT WINAPI field_get_UnderlyingValue( Field *iface, VARIANT *val )
326 FIXME( "%p, %p\n", iface, val );
327 return E_NOTIMPL;
330 static HRESULT WINAPI field_get_DataFormat( Field *iface, IUnknown **format )
332 FIXME( "%p, %p\n", iface, format );
333 return E_NOTIMPL;
336 static HRESULT WINAPI field_putref_DataFormat( Field *iface, IUnknown *format )
338 FIXME( "%p, %p\n", iface, format );
339 return E_NOTIMPL;
342 static HRESULT WINAPI field_put_Precision( Field *iface, unsigned char precision )
344 FIXME( "%p, %c\n", iface, precision );
345 return E_NOTIMPL;
348 static HRESULT WINAPI field_put_NumericScale( Field *iface, unsigned char scale )
350 FIXME( "%p, %c\n", iface, scale );
351 return E_NOTIMPL;
354 static HRESULT WINAPI field_put_Type( Field *iface, DataTypeEnum type )
356 struct field *field = impl_from_Field( iface );
358 TRACE( "%p, %u\n", field, type );
360 field->type = type;
361 return S_OK;
364 static HRESULT WINAPI field_put_DefinedSize( Field *iface, ADO_LONGPTR size )
366 struct field *field = impl_from_Field( iface );
368 TRACE( "%p, %Id\n", field, size );
370 field->defined_size = size;
371 return S_OK;
374 static HRESULT WINAPI field_put_Attributes( Field *iface, LONG attrs )
376 struct field *field = impl_from_Field( iface );
378 TRACE( "%p, %ld\n", field, attrs );
380 field->attrs = attrs;
381 return S_OK;
384 static HRESULT WINAPI field_get_Status( Field *iface, LONG *status )
386 FIXME( "%p, %p\n", iface, status );
387 return E_NOTIMPL;
390 static const struct FieldVtbl field_vtbl =
392 field_QueryInterface,
393 field_AddRef,
394 field_Release,
395 field_GetTypeInfoCount,
396 field_GetTypeInfo,
397 field_GetIDsOfNames,
398 field_Invoke,
399 field_get_Properties,
400 field_get_ActualSize,
401 field_get_Attributes,
402 field_get_DefinedSize,
403 field_get_Name,
404 field_get_Type,
405 field_get_Value,
406 field_put_Value,
407 field_get_Precision,
408 field_get_NumericScale,
409 field_AppendChunk,
410 field_GetChunk,
411 field_get_OriginalValue,
412 field_get_UnderlyingValue,
413 field_get_DataFormat,
414 field_putref_DataFormat,
415 field_put_Precision,
416 field_put_NumericScale,
417 field_put_Type,
418 field_put_DefinedSize,
419 field_put_Attributes,
420 field_get_Status
423 static inline struct field *field_from_ISupportErrorInfo( ISupportErrorInfo *iface )
425 return CONTAINING_RECORD( iface, struct field, ISupportErrorInfo_iface );
428 static HRESULT WINAPI field_supporterrorinfo_QueryInterface( ISupportErrorInfo *iface, REFIID riid, void **obj )
430 struct field *field = field_from_ISupportErrorInfo( iface );
431 return Field_QueryInterface( &field->Field_iface, riid, obj );
434 static ULONG WINAPI field_supporterrorinfo_AddRef( ISupportErrorInfo *iface )
436 struct field *field = field_from_ISupportErrorInfo( iface );
437 return Field_AddRef( &field->Field_iface );
440 static ULONG WINAPI field_supporterrorinfo_Release( ISupportErrorInfo *iface )
442 struct field *field = field_from_ISupportErrorInfo( iface );
443 return Field_Release( &field->Field_iface );
446 static HRESULT WINAPI field_supporterrorinfo_InterfaceSupportsErrorInfo( ISupportErrorInfo *iface, REFIID riid )
448 struct field *field = field_from_ISupportErrorInfo( iface );
449 FIXME( "%p, %s\n", field, debugstr_guid(riid) );
450 return S_FALSE;
453 static const ISupportErrorInfoVtbl field_supporterrorinfo_vtbl =
455 field_supporterrorinfo_QueryInterface,
456 field_supporterrorinfo_AddRef,
457 field_supporterrorinfo_Release,
458 field_supporterrorinfo_InterfaceSupportsErrorInfo
461 static HRESULT WINAPI field_props_QueryInterface(Properties *iface, REFIID riid, void **ppv)
463 struct field *field = impl_from_Properties( iface );
465 if (IsEqualGUID( riid, &IID_Properties) || IsEqualGUID( riid, &IID_IDispatch ) ||
466 IsEqualGUID( riid, &IID_IUnknown ))
468 *ppv = &field->Properties_iface;
470 else
472 FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
473 return E_NOINTERFACE;
475 Field_AddRef(&field->Field_iface);
476 return S_OK;
479 static ULONG WINAPI field_props_AddRef(Properties *iface)
481 struct field *field = impl_from_Properties( iface );
482 return Field_AddRef(&field->Field_iface);
485 static ULONG WINAPI field_props_Release(Properties *iface)
487 struct field *field = impl_from_Properties( iface );
488 return Field_Release(&field->Field_iface);
491 static HRESULT WINAPI field_props_GetTypeInfoCount(Properties *iface, UINT *count)
493 struct field *field = impl_from_Properties( iface );
494 TRACE( "%p, %p\n", field, count );
495 *count = 1;
496 return S_OK;
499 static HRESULT WINAPI field_props_GetTypeInfo(Properties *iface, UINT index, LCID lcid, ITypeInfo **info)
501 struct field *field = impl_from_Properties( iface );
502 TRACE( "%p, %u, %lu, %p\n", field, index, lcid, info );
503 return get_typeinfo(Properties_tid, info);
506 static HRESULT WINAPI field_props_GetIDsOfNames(Properties *iface, REFIID riid, LPOLESTR *names, UINT count,
507 LCID lcid, DISPID *dispid )
509 struct field *field = impl_from_Properties( iface );
510 HRESULT hr;
511 ITypeInfo *typeinfo;
513 TRACE( "%p, %s, %p, %u, %lu, %p\n", field, debugstr_guid(riid), names, count, lcid, dispid );
515 hr = get_typeinfo(Properties_tid, &typeinfo);
516 if(SUCCEEDED(hr))
518 hr = ITypeInfo_GetIDsOfNames(typeinfo, names, count, dispid);
519 ITypeInfo_Release(typeinfo);
522 return hr;
525 static HRESULT WINAPI field_props_Invoke(Properties *iface, DISPID member, REFIID riid, LCID lcid, WORD flags,
526 DISPPARAMS *params, VARIANT *result, EXCEPINFO *excep_info, UINT *arg_err )
528 struct field *field = impl_from_Properties( iface );
529 HRESULT hr;
530 ITypeInfo *typeinfo;
532 TRACE( "%p, %ld, %s, %ld, %d, %p, %p, %p, %p\n", field, member, debugstr_guid(riid), lcid, flags, params,
533 result, excep_info, arg_err );
535 hr = get_typeinfo(Properties_tid, &typeinfo);
536 if(SUCCEEDED(hr))
538 hr = ITypeInfo_Invoke(typeinfo, &field->Field_iface, member, flags, params,
539 result, excep_info, arg_err);
540 ITypeInfo_Release(typeinfo);
543 return hr;
546 static HRESULT WINAPI field_props_get_Count(Properties *iface, LONG *count)
548 struct field *field = impl_from_Properties( iface );
549 FIXME( "%p, %p\n", field, count);
550 *count = 0;
551 return S_OK;
554 static HRESULT WINAPI field_props__NewEnum(Properties *iface, IUnknown **object)
556 struct field *field = impl_from_Properties( iface );
557 FIXME( "%p, %p\n", field, object);
558 return E_NOTIMPL;
561 static HRESULT WINAPI field_props_Refresh(Properties *iface)
563 struct field *field = impl_from_Properties( iface );
564 FIXME( "%p\n", field);
565 return E_NOTIMPL;
568 static HRESULT WINAPI field_props_get_Item(Properties *iface, VARIANT index, Property **object)
570 struct field *field = impl_from_Properties( iface );
571 FIXME( "%p, %s, %p\n", field, debugstr_variant(&index), object);
572 return MAKE_ADO_HRESULT(adErrItemNotFound);
575 static struct PropertiesVtbl field_properties_vtbl =
577 field_props_QueryInterface,
578 field_props_AddRef,
579 field_props_Release,
580 field_props_GetTypeInfoCount,
581 field_props_GetTypeInfo,
582 field_props_GetIDsOfNames,
583 field_props_Invoke,
584 field_props_get_Count,
585 field_props__NewEnum,
586 field_props_Refresh,
587 field_props_get_Item
590 static HRESULT Field_create( const WCHAR *name, LONG index, struct recordset *recordset, Field **obj )
592 struct field *field;
594 if (!(field = calloc( 1, sizeof(*field) ))) return E_OUTOFMEMORY;
595 field->Field_iface.lpVtbl = &field_vtbl;
596 field->ISupportErrorInfo_iface.lpVtbl = &field_supporterrorinfo_vtbl;
597 field->Properties_iface.lpVtbl = &field_properties_vtbl;
598 field->refs = 1;
599 if (!(field->name = wcsdup( name )))
601 free( field );
602 return E_OUTOFMEMORY;
604 field->index = index;
605 field->recordset = recordset;
607 *obj = &field->Field_iface;
608 TRACE( "returning iface %p\n", *obj );
609 return S_OK;
612 static inline struct fields *impl_from_Fields( Fields *iface )
614 return CONTAINING_RECORD( iface, struct fields, Fields_iface );
617 static ULONG WINAPI fields_AddRef( Fields *iface )
619 struct fields *fields = impl_from_Fields( iface );
620 LONG refs = InterlockedIncrement( &fields->refs );
621 TRACE( "%p new refcount %ld\n", fields, refs );
622 return refs;
625 static ULONG WINAPI fields_Release( Fields *iface )
627 struct fields *fields = impl_from_Fields( iface );
628 LONG refs = InterlockedDecrement( &fields->refs );
629 TRACE( "%p new refcount %ld\n", fields, refs );
630 if (!refs)
632 if (fields->recordset) _Recordset_Release( &fields->recordset->Recordset_iface );
633 fields->recordset = NULL;
634 WARN( "not destroying %p\n", fields );
635 return InterlockedIncrement( &fields->refs );
637 return refs;
640 static HRESULT WINAPI fields_QueryInterface( Fields *iface, REFIID riid, void **obj )
642 struct fields *fields = impl_from_Fields( iface );
643 TRACE( "%p, %s, %p\n", iface, debugstr_guid(riid), obj );
645 if (IsEqualGUID( riid, &IID_Fields ) || IsEqualGUID( riid, &IID_IDispatch ) ||
646 IsEqualGUID( riid, &IID_IUnknown ))
648 *obj = iface;
650 else if (IsEqualGUID( riid, &IID_ISupportErrorInfo ))
652 *obj = &fields->ISupportErrorInfo_iface;
654 else
656 FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
657 return E_NOINTERFACE;
659 fields_AddRef( iface );
660 return S_OK;
663 static HRESULT WINAPI fields_GetTypeInfoCount( Fields *iface, UINT *count )
665 struct fields *fields = impl_from_Fields( iface );
666 TRACE( "%p, %p\n", fields, count );
667 *count = 1;
668 return S_OK;
671 static HRESULT WINAPI fields_GetTypeInfo( Fields *iface, UINT index, LCID lcid, ITypeInfo **info )
673 struct fields *fields = impl_from_Fields( iface );
674 TRACE( "%p, %u, %lu, %p\n", fields, index, lcid, info );
675 return get_typeinfo(Fields_tid, info);
678 static HRESULT WINAPI fields_GetIDsOfNames( Fields *iface, REFIID riid, LPOLESTR *names, UINT count,
679 LCID lcid, DISPID *dispid )
681 struct fields *fields = impl_from_Fields( iface );
682 HRESULT hr;
683 ITypeInfo *typeinfo;
685 TRACE( "%p, %s, %p, %u, %lu, %p\n", fields, debugstr_guid(riid), names, count, lcid, dispid );
687 hr = get_typeinfo(Fields_tid, &typeinfo);
688 if(SUCCEEDED(hr))
690 hr = ITypeInfo_GetIDsOfNames(typeinfo, names, count, dispid);
691 ITypeInfo_Release(typeinfo);
694 return hr;
697 static HRESULT WINAPI fields_Invoke( Fields *iface, DISPID member, REFIID riid, LCID lcid, WORD flags,
698 DISPPARAMS *params, VARIANT *result, EXCEPINFO *excep_info, UINT *arg_err )
700 struct fields *fields = impl_from_Fields( iface );
701 HRESULT hr;
702 ITypeInfo *typeinfo;
704 TRACE( "%p, %ld, %s, %ld, %d, %p, %p, %p, %p\n", fields, member, debugstr_guid(riid), lcid, flags, params,
705 result, excep_info, arg_err );
707 hr = get_typeinfo(Fields_tid, &typeinfo);
708 if(SUCCEEDED(hr))
710 hr = ITypeInfo_Invoke(typeinfo, &fields->Fields_iface, member, flags, params,
711 result, excep_info, arg_err);
712 ITypeInfo_Release(typeinfo);
715 return hr;
718 static HRESULT WINAPI fields_get_Count( Fields *iface, LONG *count )
720 struct fields *fields = impl_from_Fields( iface );
722 TRACE( "%p, %p\n", fields, count );
724 *count = fields->count;
725 return S_OK;
728 static HRESULT WINAPI fields__NewEnum( Fields *iface, IUnknown **obj )
730 FIXME( "%p, %p\n", iface, obj );
731 return E_NOTIMPL;
734 static HRESULT WINAPI fields_Refresh( Fields *iface )
736 FIXME( "%p\n", iface );
737 return E_NOTIMPL;
740 static HRESULT map_index( struct fields *fields, VARIANT *index, ULONG *ret )
742 ULONG i;
744 if (V_VT( index ) != VT_BSTR)
746 VARIANT idx;
748 VariantInit(&idx);
749 if (VariantChangeType(&idx, index, 0, VT_UI4) == S_OK)
751 i = V_UI4 ( &idx );
752 if (i < fields->count)
754 *ret = i;
755 return S_OK;
759 return MAKE_ADO_HRESULT(adErrItemNotFound);
762 for (i = 0; i < fields->count; i++)
764 BSTR name;
765 BOOL match;
766 HRESULT hr;
768 if ((hr = Field_get_Name( fields->field[i], &name )) != S_OK) return hr;
769 match = !wcsicmp( V_BSTR( index ), name );
770 SysFreeString( name );
771 if (match)
773 *ret = i;
774 return S_OK;
778 return MAKE_ADO_HRESULT(adErrItemNotFound);
781 static HRESULT WINAPI fields_get_Item( Fields *iface, VARIANT index, Field **obj )
783 struct fields *fields = impl_from_Fields( iface );
784 HRESULT hr;
785 ULONG i = 0;
787 TRACE( "%p, %s, %p\n", fields, debugstr_variant(&index), obj );
789 if ((hr = map_index( fields, &index, &i )) != S_OK) return hr;
791 Field_AddRef( fields->field[i] );
792 *obj = fields->field[i];
793 return S_OK;
796 static BOOL resize_fields( struct fields *fields, ULONG count )
798 if (count > fields->allocated)
800 Field **tmp;
801 ULONG new_size = max( count, fields->allocated * 2 );
802 if (!(tmp = realloc( fields->field, new_size * sizeof(*tmp) ))) return FALSE;
803 fields->field = tmp;
804 fields->allocated = new_size;
807 fields->count = count;
808 return TRUE;
811 static HRESULT append_field( struct fields *fields, BSTR name, DataTypeEnum type, LONG size, FieldAttributeEnum attr,
812 VARIANT *value )
814 Field *field;
815 HRESULT hr;
817 if ((hr = Field_create( name, fields->count, fields->recordset, &field )) != S_OK) return hr;
818 Field_put_Type( field, type );
819 Field_put_DefinedSize( field, size );
820 if (attr != adFldUnspecified) Field_put_Attributes( field, attr );
821 if (value) FIXME( "ignoring value %s\n", debugstr_variant(value) );
823 if (!(resize_fields( fields, fields->count + 1 )))
825 Field_Release( field );
826 return E_OUTOFMEMORY;
829 fields->field[fields->count - 1] = field;
830 return S_OK;
833 static HRESULT WINAPI fields__Append( Fields *iface, BSTR name, DataTypeEnum type, ADO_LONGPTR size, FieldAttributeEnum attr )
835 struct fields *fields = impl_from_Fields( iface );
837 TRACE( "%p, %s, %u, %Id, %d\n", fields, debugstr_w(name), type, size, attr );
839 return append_field( fields, name, type, size, attr, NULL );
842 static HRESULT WINAPI fields_Delete( Fields *iface, VARIANT index )
844 FIXME( "%p, %s\n", iface, debugstr_variant(&index) );
845 return E_NOTIMPL;
848 static HRESULT WINAPI fields_Append( Fields *iface, BSTR name, DataTypeEnum type, ADO_LONGPTR size, FieldAttributeEnum attr,
849 VARIANT value )
851 struct fields *fields = impl_from_Fields( iface );
853 TRACE( "%p, %s, %u, %Id, %d, %s\n", fields, debugstr_w(name), type, size, attr, debugstr_variant(&value) );
855 return append_field( fields, name, type, size, attr, &value );
858 static HRESULT WINAPI fields_Update( Fields *iface )
860 FIXME( "%p\n", iface );
861 return E_NOTIMPL;
864 static HRESULT WINAPI fields_Resync( Fields *iface, ResyncEnum resync_values )
866 FIXME( "%p, %u\n", iface, resync_values );
867 return E_NOTIMPL;
870 static HRESULT WINAPI fields_CancelUpdate( Fields *iface )
872 FIXME( "%p\n", iface );
873 return E_NOTIMPL;
876 static const struct FieldsVtbl fields_vtbl =
878 fields_QueryInterface,
879 fields_AddRef,
880 fields_Release,
881 fields_GetTypeInfoCount,
882 fields_GetTypeInfo,
883 fields_GetIDsOfNames,
884 fields_Invoke,
885 fields_get_Count,
886 fields__NewEnum,
887 fields_Refresh,
888 fields_get_Item,
889 fields__Append,
890 fields_Delete,
891 fields_Append,
892 fields_Update,
893 fields_Resync,
894 fields_CancelUpdate
897 static inline struct fields *fields_from_ISupportErrorInfo( ISupportErrorInfo *iface )
899 return CONTAINING_RECORD( iface, struct fields, ISupportErrorInfo_iface );
902 static HRESULT WINAPI fields_supporterrorinfo_QueryInterface( ISupportErrorInfo *iface, REFIID riid, void **obj )
904 struct fields *fields = fields_from_ISupportErrorInfo( iface );
905 return Fields_QueryInterface( &fields->Fields_iface, riid, obj );
908 static ULONG WINAPI fields_supporterrorinfo_AddRef( ISupportErrorInfo *iface )
910 struct fields *fields = fields_from_ISupportErrorInfo( iface );
911 return Fields_AddRef( &fields->Fields_iface );
914 static ULONG WINAPI fields_supporterrorinfo_Release( ISupportErrorInfo *iface )
916 struct fields *fields = fields_from_ISupportErrorInfo( iface );
917 return Fields_Release( &fields->Fields_iface );
920 static HRESULT WINAPI fields_supporterrorinfo_InterfaceSupportsErrorInfo( ISupportErrorInfo *iface, REFIID riid )
922 struct fields *fields = fields_from_ISupportErrorInfo( iface );
923 FIXME( "%p, %s\n", fields, debugstr_guid(riid) );
924 return S_FALSE;
927 static const ISupportErrorInfoVtbl fields_supporterrorinfo_vtbl =
929 fields_supporterrorinfo_QueryInterface,
930 fields_supporterrorinfo_AddRef,
931 fields_supporterrorinfo_Release,
932 fields_supporterrorinfo_InterfaceSupportsErrorInfo
935 static void map_rowset_fields(struct recordset *recordset, struct fields *fields)
937 HRESULT hr;
938 IColumnsInfo *columninfo;
939 DBORDINAL columns, i;
940 DBCOLUMNINFO *colinfo;
941 OLECHAR *stringsbuffer;
943 /* Not Finding the interface or GetColumnInfo failing just causes 0 Fields to be returned */
944 hr = IRowset_QueryInterface(recordset->row_set, &IID_IColumnsInfo, (void**)&columninfo);
945 if (FAILED(hr))
946 return;
948 hr = IColumnsInfo_GetColumnInfo(columninfo, &columns, &colinfo, &stringsbuffer);
949 if (SUCCEEDED(hr))
951 for (i=0; i < columns; i++)
953 TRACE("Adding Column %Iu, pwszName: %s, pTypeInfo %p, iOrdinal %Iu, dwFlags 0x%08lx, "
954 "ulColumnSize %Iu, wType %d, bPrecision %d, bScale %d\n",
955 i, debugstr_w(colinfo[i].pwszName), colinfo[i].pTypeInfo, colinfo[i].iOrdinal,
956 colinfo[i].dwFlags, colinfo[i].ulColumnSize, colinfo[i].wType,
957 colinfo[i].bPrecision, colinfo[i].bScale);
959 hr = append_field(fields, colinfo[i].pwszName, colinfo[i].wType, colinfo[i].ulColumnSize,
960 colinfo[i].dwFlags, NULL);
961 if (FAILED(hr))
963 ERR("Failed to add Field name - 0x%08lx\n", hr);
964 return;
968 CoTaskMemFree(colinfo);
969 CoTaskMemFree(stringsbuffer);
972 IColumnsInfo_Release(columninfo);
975 static HRESULT fields_create( struct recordset *recordset, struct fields **ret )
977 struct fields *fields;
979 if (!(fields = calloc( 1, sizeof(*fields) ))) return E_OUTOFMEMORY;
980 fields->Fields_iface.lpVtbl = &fields_vtbl;
981 fields->ISupportErrorInfo_iface.lpVtbl = &fields_supporterrorinfo_vtbl;
982 fields->refs = 1;
983 fields->recordset = recordset;
984 _Recordset_AddRef( &fields->recordset->Recordset_iface );
986 if ( recordset->row_set )
987 map_rowset_fields(recordset, fields);
989 *ret = fields;
990 TRACE( "returning %p\n", *ret );
991 return S_OK;
994 static inline struct recordset *impl_from_Recordset( _Recordset *iface )
996 return CONTAINING_RECORD( iface, struct recordset, Recordset_iface );
999 static inline struct recordset *impl_from_ADORecordsetConstruction( ADORecordsetConstruction *iface )
1001 return CONTAINING_RECORD( iface, struct recordset, ADORecordsetConstruction_iface );
1004 static ULONG WINAPI recordset_AddRef( _Recordset *iface )
1006 struct recordset *recordset = impl_from_Recordset( iface );
1007 LONG refs = InterlockedIncrement( &recordset->refs );
1008 TRACE( "%p new refcount %ld\n", recordset, refs );
1009 return refs;
1012 static void close_recordset( struct recordset *recordset )
1014 ULONG row, col, col_count;
1015 ULONG i;
1017 if ( recordset->row_set ) IRowset_Release( recordset->row_set );
1018 recordset->row_set = NULL;
1020 if (!recordset->fields) return;
1021 col_count = get_column_count( recordset );
1023 for (i = 0; i < col_count; i++)
1025 struct field *field = impl_from_Field( recordset->fields->field[i] );
1026 field->recordset = NULL;
1027 Field_Release(&field->Field_iface);
1029 recordset->fields->count = 0;
1030 Fields_Release( &recordset->fields->Fields_iface );
1031 recordset->fields = NULL;
1033 for (row = 0; row < recordset->count; row++)
1034 for (col = 0; col < col_count; col++) VariantClear( &recordset->data[row * col_count + col] );
1036 recordset->count = recordset->allocated = recordset->index = 0;
1037 free( recordset->data );
1038 recordset->data = NULL;
1041 static ULONG WINAPI recordset_Release( _Recordset *iface )
1043 struct recordset *recordset = impl_from_Recordset( iface );
1044 LONG refs = InterlockedDecrement( &recordset->refs );
1045 TRACE( "%p new refcount %ld\n", recordset, refs );
1046 if (!refs)
1048 TRACE( "destroying %p\n", recordset );
1049 close_recordset( recordset );
1050 free( recordset );
1052 return refs;
1055 static HRESULT WINAPI recordset_QueryInterface( _Recordset *iface, REFIID riid, void **obj )
1057 struct recordset *recordset = impl_from_Recordset( iface );
1058 TRACE( "%p, %s, %p\n", iface, debugstr_guid(riid), obj );
1060 *obj = NULL;
1062 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch) ||
1063 IsEqualIID(riid, &IID__ADO) || IsEqualIID(riid, &IID_Recordset15) ||
1064 IsEqualIID(riid, &IID_Recordset20) || IsEqualIID(riid, &IID_Recordset21) ||
1065 IsEqualIID(riid, &IID__Recordset))
1067 *obj = iface;
1069 else if (IsEqualGUID( riid, &IID_ISupportErrorInfo ))
1071 *obj = &recordset->ISupportErrorInfo_iface;
1073 else if (IsEqualGUID( riid, &IID_ADORecordsetConstruction ))
1075 *obj = &recordset->ADORecordsetConstruction_iface;
1077 else if (IsEqualGUID( riid, &IID_IRunnableObject ))
1079 TRACE("IID_IRunnableObject not supported returning NULL\n");
1080 return E_NOINTERFACE;
1082 else
1084 FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
1085 return E_NOINTERFACE;
1087 recordset_AddRef( iface );
1088 return S_OK;
1091 static HRESULT WINAPI recordset_GetTypeInfoCount( _Recordset *iface, UINT *count )
1093 struct recordset *recordset = impl_from_Recordset( iface );
1094 TRACE( "%p, %p\n", recordset, count );
1095 *count = 1;
1096 return S_OK;
1099 static HRESULT WINAPI recordset_GetTypeInfo( _Recordset *iface, UINT index, LCID lcid, ITypeInfo **info )
1101 struct recordset *recordset = impl_from_Recordset( iface );
1102 TRACE( "%p, %u, %lu, %p\n", recordset, index, lcid, info );
1103 return get_typeinfo(Recordset_tid, info);
1106 static HRESULT WINAPI recordset_GetIDsOfNames( _Recordset *iface, REFIID riid, LPOLESTR *names, UINT count,
1107 LCID lcid, DISPID *dispid )
1109 struct recordset *recordset = impl_from_Recordset( iface );
1110 HRESULT hr;
1111 ITypeInfo *typeinfo;
1113 TRACE( "%p, %s, %p, %u, %lu, %p\n", recordset, debugstr_guid(riid), names, count, lcid, dispid );
1115 hr = get_typeinfo(Recordset_tid, &typeinfo);
1116 if(SUCCEEDED(hr))
1118 hr = ITypeInfo_GetIDsOfNames(typeinfo, names, count, dispid);
1119 ITypeInfo_Release(typeinfo);
1122 return hr;
1125 static HRESULT WINAPI recordset_Invoke( _Recordset *iface, DISPID member, REFIID riid, LCID lcid, WORD flags,
1126 DISPPARAMS *params, VARIANT *result, EXCEPINFO *excep_info, UINT *arg_err )
1128 struct recordset *recordset = impl_from_Recordset( iface );
1129 HRESULT hr;
1130 ITypeInfo *typeinfo;
1132 TRACE( "%p, %ld, %s, %ld, %d, %p, %p, %p, %p\n", recordset, member, debugstr_guid(riid), lcid, flags, params,
1133 result, excep_info, arg_err );
1135 hr = get_typeinfo(Recordset_tid, &typeinfo);
1136 if(SUCCEEDED(hr))
1138 hr = ITypeInfo_Invoke(typeinfo, &recordset->Recordset_iface, member, flags, params,
1139 result, excep_info, arg_err);
1140 ITypeInfo_Release(typeinfo);
1143 return hr;
1146 static HRESULT WINAPI recordset_get_Properties( _Recordset *iface, Properties **obj )
1148 FIXME( "%p, %p\n", iface, obj );
1149 return E_NOTIMPL;
1152 static HRESULT WINAPI recordset_get_AbsolutePosition( _Recordset *iface, PositionEnum_Param *pos )
1154 FIXME( "%p, %p\n", iface, pos );
1155 return E_NOTIMPL;
1158 static HRESULT WINAPI recordset_put_AbsolutePosition( _Recordset *iface, PositionEnum_Param pos )
1160 FIXME( "%p, %Id\n", iface, pos );
1161 return E_NOTIMPL;
1164 static HRESULT WINAPI recordset_putref_ActiveConnection( _Recordset *iface, IDispatch *connection )
1166 FIXME( "%p, %p\n", iface, connection );
1167 return E_NOTIMPL;
1170 static HRESULT WINAPI recordset_put_ActiveConnection( _Recordset *iface, VARIANT connection )
1172 FIXME( "%p, %s\n", iface, debugstr_variant(&connection) );
1173 return E_NOTIMPL;
1176 static HRESULT WINAPI recordset_get_ActiveConnection( _Recordset *iface, VARIANT *connection )
1178 FIXME( "%p, %p\n", iface, connection );
1179 return E_NOTIMPL;
1182 static HRESULT WINAPI recordset_get_BOF( _Recordset *iface, VARIANT_BOOL *bof )
1184 struct recordset *recordset = impl_from_Recordset( iface );
1186 TRACE( "%p, %p\n", recordset, bof );
1188 *bof = (recordset->index < 0) ? VARIANT_TRUE : VARIANT_FALSE;
1189 return S_OK;
1192 static HRESULT WINAPI recordset_get_Bookmark( _Recordset *iface, VARIANT *bookmark )
1194 struct recordset *recordset = impl_from_Recordset( iface );
1195 TRACE( "%p, %p\n", iface, bookmark );
1197 if (recordset->state == adStateClosed) return MAKE_ADO_HRESULT( adErrObjectClosed );
1198 if (recordset->index < 0) return MAKE_ADO_HRESULT( adErrNoCurrentRecord );
1200 V_VT(bookmark) = VT_I4;
1201 V_I4(bookmark) = recordset->index;
1202 return S_OK;
1205 static HRESULT WINAPI recordset_put_Bookmark( _Recordset *iface, VARIANT bookmark )
1207 struct recordset *recordset = impl_from_Recordset( iface );
1208 TRACE( "%p, %s\n", iface, debugstr_variant(&bookmark) );
1210 if (recordset->state == adStateClosed) return MAKE_ADO_HRESULT( adErrObjectClosed );
1212 if (V_VT(&bookmark) != VT_I4) return MAKE_ADO_HRESULT( adErrInvalidArgument );
1214 recordset->index = V_I4(&bookmark);
1215 return S_OK;
1218 static HRESULT WINAPI recordset_get_CacheSize( _Recordset *iface, LONG *size )
1220 FIXME( "%p, %p\n", iface, size );
1221 return E_NOTIMPL;
1224 static HRESULT WINAPI recordset_put_CacheSize( _Recordset *iface, LONG size )
1226 FIXME( "%p, %ld\n", iface, size );
1227 return E_NOTIMPL;
1230 static HRESULT WINAPI recordset_get_CursorType( _Recordset *iface, CursorTypeEnum *cursor_type )
1232 struct recordset *recordset = impl_from_Recordset( iface );
1234 TRACE( "%p, %p\n", iface, cursor_type );
1236 *cursor_type = recordset->cursor_type;
1237 return S_OK;
1240 static HRESULT WINAPI recordset_put_CursorType( _Recordset *iface, CursorTypeEnum cursor_type )
1242 struct recordset *recordset = impl_from_Recordset( iface );
1244 TRACE( "%p, %d\n", iface, cursor_type );
1246 recordset->cursor_type = cursor_type;
1247 return S_OK;
1250 static HRESULT WINAPI recordset_get_EOF( _Recordset *iface, VARIANT_BOOL *eof )
1252 struct recordset *recordset = impl_from_Recordset( iface );
1254 TRACE( "%p, %p\n", recordset, eof );
1256 *eof = (!recordset->count || recordset->index >= recordset->count) ? VARIANT_TRUE : VARIANT_FALSE;
1257 return S_OK;
1260 static HRESULT WINAPI recordset_get_Fields( _Recordset *iface, Fields **obj )
1262 struct recordset *recordset = impl_from_Recordset( iface );
1263 HRESULT hr;
1265 TRACE( "%p, %p\n", recordset, obj );
1267 if (recordset->fields)
1269 /* yes, this adds a reference to the recordset instead of the fields object */
1270 _Recordset_AddRef( &recordset->Recordset_iface );
1271 recordset->fields->recordset = recordset;
1272 *obj = &recordset->fields->Fields_iface;
1273 return S_OK;
1276 if ((hr = fields_create( recordset, &recordset->fields )) != S_OK) return hr;
1278 *obj = &recordset->fields->Fields_iface;
1279 return S_OK;
1282 static HRESULT WINAPI recordset_get_LockType( _Recordset *iface, LockTypeEnum *lock_type )
1284 FIXME( "%p, %p\n", iface, lock_type );
1285 return E_NOTIMPL;
1288 static HRESULT WINAPI recordset_put_LockType( _Recordset *iface, LockTypeEnum lock_type )
1290 FIXME( "%p, %d\n", iface, lock_type );
1291 return E_NOTIMPL;
1294 static HRESULT WINAPI recordset_get_MaxRecords( _Recordset *iface, ADO_LONGPTR *max_records )
1296 FIXME( "%p, %p\n", iface, max_records );
1297 return E_NOTIMPL;
1300 static HRESULT WINAPI recordset_put_MaxRecords( _Recordset *iface, ADO_LONGPTR max_records )
1302 FIXME( "%p, %Id\n", iface, max_records );
1303 return E_NOTIMPL;
1306 static HRESULT WINAPI recordset_get_RecordCount( _Recordset *iface, ADO_LONGPTR *count )
1308 struct recordset *recordset = impl_from_Recordset( iface );
1310 TRACE( "%p, %p\n", recordset, count );
1312 *count = recordset->count;
1313 return S_OK;
1316 static HRESULT WINAPI recordset_putref_Source( _Recordset *iface, IDispatch *source )
1318 FIXME( "%p, %p\n", iface, source );
1319 return E_NOTIMPL;
1322 static HRESULT WINAPI recordset_put_Source( _Recordset *iface, BSTR source )
1324 FIXME( "%p, %s\n", iface, debugstr_w(source) );
1325 return E_NOTIMPL;
1328 static HRESULT WINAPI recordset_get_Source( _Recordset *iface, VARIANT *source )
1330 FIXME( "%p, %p\n", iface, source );
1331 return E_NOTIMPL;
1334 static BOOL resize_recordset( struct recordset *recordset, ULONG row_count )
1336 ULONG row_size = get_column_count( recordset ) * sizeof(*recordset->data);
1338 if (row_count > recordset->allocated)
1340 VARIANT *tmp;
1341 ULONG count = max( row_count, recordset->allocated * 2 );
1342 if (!(tmp = realloc( recordset->data, count * row_size ))) return FALSE;
1343 memset( tmp + recordset->allocated, 0, (count - recordset->allocated) * row_size );
1344 recordset->data = tmp;
1345 recordset->allocated = count;
1348 recordset->count = row_count;
1349 return TRUE;
1352 static HRESULT WINAPI recordset_AddNew( _Recordset *iface, VARIANT field_list, VARIANT values )
1354 struct recordset *recordset = impl_from_Recordset( iface );
1356 TRACE( "%p, %s, %s\n", recordset, debugstr_variant(&field_list), debugstr_variant(&values) );
1357 FIXME( "ignoring field list and values\n" );
1359 if (recordset->state == adStateClosed) return MAKE_ADO_HRESULT( adErrObjectClosed );
1361 if (!resize_recordset( recordset, recordset->count + 1 )) return E_OUTOFMEMORY;
1362 recordset->index++;
1363 return S_OK;
1366 static HRESULT WINAPI recordset_CancelUpdate( _Recordset *iface )
1368 FIXME( "%p\n", iface );
1369 return E_NOTIMPL;
1372 static HRESULT WINAPI recordset_Close( _Recordset *iface )
1374 struct recordset *recordset = impl_from_Recordset( iface );
1376 TRACE( "%p\n", recordset );
1378 if (recordset->state == adStateClosed) return MAKE_ADO_HRESULT( adErrObjectClosed );
1380 close_recordset( recordset );
1381 recordset->state = adStateClosed;
1382 return S_OK;
1385 static HRESULT WINAPI recordset_Delete( _Recordset *iface, AffectEnum affect_records )
1387 FIXME( "%p, %u\n", iface, affect_records );
1388 return E_NOTIMPL;
1391 static HRESULT WINAPI recordset_GetRows( _Recordset *iface, LONG rows, VARIANT start, VARIANT fields, VARIANT *var )
1393 FIXME( "%p, %ld, %s, %s, %p\n", iface, rows, debugstr_variant(&start), debugstr_variant(&fields), var );
1394 return E_NOTIMPL;
1397 static HRESULT WINAPI recordset_Move( _Recordset *iface, ADO_LONGPTR num_records, VARIANT start )
1399 FIXME( "%p, %Id, %s\n", iface, num_records, debugstr_variant(&start) );
1400 return E_NOTIMPL;
1403 static HRESULT WINAPI recordset_MoveNext( _Recordset *iface )
1405 struct recordset *recordset = impl_from_Recordset( iface );
1407 TRACE( "%p\n", recordset );
1409 if (recordset->index < recordset->count) recordset->index++;
1410 return S_OK;
1413 static HRESULT WINAPI recordset_MovePrevious( _Recordset *iface )
1415 struct recordset *recordset = impl_from_Recordset( iface );
1417 TRACE( "%p\n", recordset );
1419 if (recordset->index >= 0) recordset->index--;
1420 return S_OK;
1423 static HRESULT WINAPI recordset_MoveFirst( _Recordset *iface )
1425 struct recordset *recordset = impl_from_Recordset( iface );
1427 TRACE( "%p\n", recordset );
1429 recordset->index = 0;
1430 return S_OK;
1433 static HRESULT WINAPI recordset_MoveLast( _Recordset *iface )
1435 struct recordset *recordset = impl_from_Recordset( iface );
1437 TRACE( "%p\n", recordset );
1439 recordset->index = (recordset->count > 0) ? recordset->count - 1 : 0;
1440 return S_OK;
1443 static HRESULT create_command_text(IUnknown *session, BSTR command, ICommandText **cmd_text)
1445 HRESULT hr;
1446 IOpenRowset *openrowset;
1447 ICommandText *command_text;
1448 ICommand *cmd;
1449 IDBCreateCommand *create_command;
1451 hr = IUnknown_QueryInterface(session, &IID_IOpenRowset, (void**)&openrowset);
1452 if (FAILED(hr))
1453 return hr;
1455 hr = IOpenRowset_QueryInterface(openrowset, &IID_IDBCreateCommand, (void**)&create_command);
1456 IOpenRowset_Release(openrowset);
1457 if (FAILED(hr))
1458 return hr;
1460 hr = IDBCreateCommand_CreateCommand(create_command, NULL, &IID_IUnknown, (IUnknown **)&cmd);
1461 IDBCreateCommand_Release(create_command);
1462 if (FAILED(hr))
1463 return hr;
1465 hr = ICommand_QueryInterface(cmd, &IID_ICommandText, (void**)&command_text);
1466 ICommand_Release(cmd);
1467 if (FAILED(hr))
1469 FIXME("Currently only ICommandText interface is support\n");
1470 return hr;
1473 hr = ICommandText_SetCommandText(command_text, &DBGUID_DEFAULT, command);
1474 if (FAILED(hr))
1476 ICommandText_Release(command_text);
1477 return hr;
1480 *cmd_text = command_text;
1482 return S_OK;
1485 static HRESULT WINAPI recordset_Open( _Recordset *iface, VARIANT source, VARIANT active_connection,
1486 CursorTypeEnum cursor_type, LockTypeEnum lock_type, LONG options )
1488 struct recordset *recordset = impl_from_Recordset( iface );
1489 ADOConnectionConstruction15 *construct;
1490 IUnknown *session;
1491 ICommandText *command_text;
1492 DBROWCOUNT affected;
1493 IUnknown *rowset;
1494 HRESULT hr;
1496 FIXME( "%p, %s, %s, %d, %d, %ld Semi-stub\n", recordset, debugstr_variant(&source), debugstr_variant(&active_connection),
1497 cursor_type, lock_type, options );
1499 if (recordset->state == adStateOpen) return MAKE_ADO_HRESULT( adErrObjectOpen );
1501 if (recordset->fields)
1503 recordset->state = adStateOpen;
1504 return S_OK;
1507 if (V_VT(&active_connection) != VT_DISPATCH)
1509 FIXME("Unsupported Active connection type %d\n", V_VT(&active_connection));
1510 return MAKE_ADO_HRESULT( adErrInvalidConnection );
1513 hr = IDispatch_QueryInterface(V_DISPATCH(&active_connection), &IID_ADOConnectionConstruction15, (void**)&construct);
1514 if (FAILED(hr))
1515 return E_FAIL;
1517 hr = ADOConnectionConstruction15_get_Session(construct, &session);
1518 ADOConnectionConstruction15_Release(construct);
1519 if (FAILED(hr))
1520 return E_FAIL;
1522 if (V_VT(&source) != VT_BSTR)
1524 FIXME("Unsupported source type!\n");
1525 IUnknown_Release(session);
1526 return E_FAIL;
1529 hr = create_command_text(session, V_BSTR(&source), &command_text);
1530 IUnknown_Release(session);
1531 if (FAILED(hr))
1532 return hr;
1534 hr = ICommandText_Execute(command_text, NULL, &IID_IUnknown, NULL, &affected, &rowset);
1535 ICommandText_Release(command_text);
1536 if (FAILED(hr) || !rowset)
1537 return hr;
1539 ADORecordsetConstruction_put_Rowset(&recordset->ADORecordsetConstruction_iface, rowset);
1540 recordset->cursor_type = cursor_type;
1541 recordset->state = adStateOpen;
1543 IUnknown_Release(rowset);
1545 return hr;
1548 static HRESULT WINAPI recordset_Requery( _Recordset *iface, LONG options )
1550 FIXME( "%p, %ld\n", iface, options );
1551 return E_NOTIMPL;
1554 static HRESULT WINAPI recordset__xResync( _Recordset *iface, AffectEnum affect_records )
1556 FIXME( "%p, %u\n", iface, affect_records );
1557 return E_NOTIMPL;
1560 static HRESULT WINAPI recordset_Update( _Recordset *iface, VARIANT fields, VARIANT values )
1562 FIXME( "%p, %s, %s\n", iface, debugstr_variant(&fields), debugstr_variant(&values) );
1563 return E_NOTIMPL;
1566 static HRESULT WINAPI recordset_get_AbsolutePage( _Recordset *iface, PositionEnum_Param *pos )
1568 FIXME( "%p, %p\n", iface, pos );
1569 return E_NOTIMPL;
1572 static HRESULT WINAPI recordset_put_AbsolutePage( _Recordset *iface, PositionEnum_Param pos )
1574 FIXME( "%p, %Id\n", iface, pos );
1575 return E_NOTIMPL;
1578 static HRESULT WINAPI recordset_get_EditMode( _Recordset *iface, EditModeEnum *mode )
1580 struct recordset *recordset = impl_from_Recordset( iface );
1581 TRACE( "%p, %p\n", iface, mode );
1583 if (recordset->state == adStateClosed) return MAKE_ADO_HRESULT( adErrObjectClosed );
1584 if (recordset->index < 0) return MAKE_ADO_HRESULT( adErrNoCurrentRecord );
1586 *mode = recordset->editmode;
1587 return S_OK;
1590 static HRESULT WINAPI recordset_get_Filter( _Recordset *iface, VARIANT *criteria )
1592 struct recordset *recordset = impl_from_Recordset( iface );
1593 TRACE( "%p, %p\n", iface, criteria );
1595 if (!criteria) return MAKE_ADO_HRESULT( adErrInvalidArgument );
1597 VariantCopy(criteria, &recordset->filter);
1598 return S_OK;
1601 static HRESULT WINAPI recordset_put_Filter( _Recordset *iface, VARIANT criteria )
1603 struct recordset *recordset = impl_from_Recordset( iface );
1604 TRACE( "%p, %s\n", recordset, debugstr_variant(&criteria) );
1606 if (V_VT(&criteria) != VT_I2 && V_VT(&criteria) != VT_I4 && V_VT(&criteria) != VT_BSTR)
1607 return MAKE_ADO_HRESULT( adErrInvalidArgument );
1609 if (V_VT(&criteria) == VT_BSTR && recordset->state == adStateOpen)
1611 FIXME("Validating fields not preformed\n");
1614 VariantCopy(&recordset->filter, &criteria);
1615 return S_OK;
1618 static HRESULT WINAPI recordset_get_PageCount( _Recordset *iface, ADO_LONGPTR *count )
1620 FIXME( "%p, %p\n", iface, count );
1621 return E_NOTIMPL;
1624 static HRESULT WINAPI recordset_get_PageSize( _Recordset *iface, LONG *size )
1626 FIXME( "%p, %p\n", iface, size );
1627 return E_NOTIMPL;
1630 static HRESULT WINAPI recordset_put_PageSize( _Recordset *iface, LONG size )
1632 FIXME( "%p, %ld\n", iface, size );
1633 return E_NOTIMPL;
1636 static HRESULT WINAPI recordset_get_Sort( _Recordset *iface, BSTR *criteria )
1638 FIXME( "%p, %p\n", iface, criteria );
1639 return E_NOTIMPL;
1642 static HRESULT WINAPI recordset_put_Sort( _Recordset *iface, BSTR criteria )
1644 FIXME( "%p, %s\n", iface, debugstr_w(criteria) );
1645 return E_NOTIMPL;
1648 static HRESULT WINAPI recordset_get_Status( _Recordset *iface, LONG *status )
1650 FIXME( "%p, %p\n", iface, status );
1651 return E_NOTIMPL;
1654 static HRESULT WINAPI recordset_get_State( _Recordset *iface, LONG *state )
1656 struct recordset *recordset = impl_from_Recordset( iface );
1658 TRACE( "%p, %p\n", recordset, state );
1660 *state = recordset->state;
1661 return S_OK;
1664 static HRESULT WINAPI recordset__xClone( _Recordset *iface, _Recordset **obj )
1666 FIXME( "%p, %p\n", iface, obj );
1667 return E_NOTIMPL;
1670 static HRESULT WINAPI recordset_UpdateBatch( _Recordset *iface, AffectEnum affect_records )
1672 FIXME( "%p, %u\n", iface, affect_records );
1673 return E_NOTIMPL;
1676 static HRESULT WINAPI recordset_CancelBatch( _Recordset *iface, AffectEnum affect_records )
1678 FIXME( "%p, %u\n", iface, affect_records );
1679 return E_NOTIMPL;
1682 static HRESULT WINAPI recordset_get_CursorLocation( _Recordset *iface, CursorLocationEnum *cursor_loc )
1684 struct recordset *recordset = impl_from_Recordset( iface );
1686 TRACE( "%p, %p\n", iface, cursor_loc );
1688 *cursor_loc = recordset->cursor_location;
1690 return S_OK;
1693 static HRESULT WINAPI recordset_put_CursorLocation( _Recordset *iface, CursorLocationEnum cursor_loc )
1695 struct recordset *recordset = impl_from_Recordset( iface );
1697 TRACE( "%p, %u\n", iface, cursor_loc );
1699 if (recordset->state == adStateOpen) return MAKE_ADO_HRESULT( adErrObjectOpen );
1701 recordset->cursor_location = cursor_loc;
1703 return S_OK;
1706 static HRESULT WINAPI recordset_NextRecordset( _Recordset *iface, VARIANT *records_affected, _Recordset **record_set )
1708 FIXME( "%p, %p, %p\n", iface, records_affected, record_set );
1709 return E_NOTIMPL;
1712 static HRESULT WINAPI recordset_Supports( _Recordset *iface, CursorOptionEnum cursor_options, VARIANT_BOOL *ret )
1714 FIXME( "%p, %08x, %p\n", iface, cursor_options, ret );
1715 return E_NOTIMPL;
1718 static HRESULT WINAPI recordset_get_Collect( _Recordset *iface, VARIANT index, VARIANT *var )
1720 FIXME( "%p, %s, %p\n", iface, debugstr_variant(&index), var );
1721 return E_NOTIMPL;
1724 static HRESULT WINAPI recordset_put_Collect( _Recordset *iface, VARIANT index, VARIANT var )
1726 FIXME( "%p, %s, %s\n", iface, debugstr_variant(&index), debugstr_variant(&var) );
1727 return E_NOTIMPL;
1730 static HRESULT WINAPI recordset_get_MarshalOptions( _Recordset *iface, MarshalOptionsEnum *options )
1732 FIXME( "%p, %p\n", iface, options );
1733 return E_NOTIMPL;
1736 static HRESULT WINAPI recordset_put_MarshalOptions( _Recordset *iface, MarshalOptionsEnum options )
1738 FIXME( "%p, %u\n", iface, options );
1739 return E_NOTIMPL;
1742 static HRESULT WINAPI recordset_Find( _Recordset *iface, BSTR criteria, LONG skip_records,
1743 SearchDirectionEnum search_direction, VARIANT start )
1745 FIXME( "%p, %s, %ld, %d, %s\n", iface, debugstr_w(criteria), skip_records, search_direction,
1746 debugstr_variant(&start) );
1747 return E_NOTIMPL;
1750 static HRESULT WINAPI recordset_Cancel( _Recordset *iface )
1752 FIXME( "%p\n", iface );
1753 return E_NOTIMPL;
1756 static HRESULT WINAPI recordset_get_DataSource( _Recordset *iface, IUnknown **data_source )
1758 FIXME( "%p, %p\n", iface, data_source );
1759 return E_NOTIMPL;
1762 static HRESULT WINAPI recordset_putref_DataSource( _Recordset *iface, IUnknown *data_source )
1764 FIXME( "%p, %p\n", iface, data_source );
1765 return E_NOTIMPL;
1768 static HRESULT WINAPI recordset__xSave( _Recordset *iface, BSTR filename, PersistFormatEnum persist_format )
1770 FIXME( "%p, %s, %u\n", iface, debugstr_w(filename), persist_format );
1771 return E_NOTIMPL;
1774 static HRESULT WINAPI recordset_get_ActiveCommand( _Recordset *iface, IDispatch **cmd )
1776 FIXME( "%p, %p\n", iface, cmd );
1777 return E_NOTIMPL;
1780 static HRESULT WINAPI recordset_put_StayInSync( _Recordset *iface, VARIANT_BOOL stay_in_sync )
1782 FIXME( "%p, %d\n", iface, stay_in_sync );
1783 return E_NOTIMPL;
1786 static HRESULT WINAPI recordset_get_StayInSync( _Recordset *iface, VARIANT_BOOL *stay_in_sync )
1788 FIXME( "%p, %p\n", iface, stay_in_sync );
1789 return E_NOTIMPL;
1792 static HRESULT WINAPI recordset_GetString( _Recordset *iface, StringFormatEnum string_format, LONG num_rows,
1793 BSTR column_delimiter, BSTR row_delimiter, BSTR null_expr,
1794 BSTR *ret_string )
1796 FIXME( "%p, %u, %ld, %s, %s, %s, %p\n", iface, string_format, num_rows, debugstr_w(column_delimiter),
1797 debugstr_w(row_delimiter), debugstr_w(null_expr), ret_string );
1798 return E_NOTIMPL;
1801 static HRESULT WINAPI recordset_get_DataMember( _Recordset *iface, BSTR *data_member )
1803 FIXME( "%p, %p\n", iface, data_member );
1804 return E_NOTIMPL;
1807 static HRESULT WINAPI recordset_put_DataMember( _Recordset *iface, BSTR data_member )
1809 FIXME( "%p, %s\n", iface, debugstr_w(data_member) );
1810 return E_NOTIMPL;
1813 static HRESULT WINAPI recordset_CompareBookmarks( _Recordset *iface, VARIANT bookmark1, VARIANT bookmark2, CompareEnum *compare )
1815 FIXME( "%p, %s, %s, %p\n", iface, debugstr_variant(&bookmark1), debugstr_variant(&bookmark2), compare );
1816 return E_NOTIMPL;
1819 static HRESULT WINAPI recordset_Clone( _Recordset *iface, LockTypeEnum lock_type, _Recordset **obj )
1821 struct recordset *recordset = impl_from_Recordset( iface );
1822 FIXME( "%p, %d, %p\n", recordset, lock_type, obj );
1824 *obj = iface;
1825 recordset_AddRef( iface );
1826 return S_OK;
1829 static HRESULT WINAPI recordset_Resync( _Recordset *iface, AffectEnum affect_records, ResyncEnum resync_values )
1831 FIXME( "%p, %u, %u\n", iface, affect_records, resync_values );
1832 return E_NOTIMPL;
1835 static HRESULT WINAPI recordset_Seek( _Recordset *iface, VARIANT key_values, SeekEnum seek_option )
1837 FIXME( "%p, %s, %u\n", iface, debugstr_variant(&key_values), seek_option );
1838 return E_NOTIMPL;
1841 static HRESULT WINAPI recordset_put_Index( _Recordset *iface, BSTR index )
1843 FIXME( "%p, %s\n", iface, debugstr_w(index) );
1844 return E_NOTIMPL;
1847 static HRESULT WINAPI recordset_get_Index( _Recordset *iface, BSTR *index )
1849 FIXME( "%p, %p\n", iface, index );
1850 return E_NOTIMPL;
1853 static HRESULT WINAPI recordset_Save( _Recordset *iface, VARIANT destination, PersistFormatEnum persist_format )
1855 FIXME( "%p, %s, %u\n", iface, debugstr_variant(&destination), persist_format );
1856 return E_NOTIMPL;
1859 static const struct _RecordsetVtbl recordset_vtbl =
1861 recordset_QueryInterface,
1862 recordset_AddRef,
1863 recordset_Release,
1864 recordset_GetTypeInfoCount,
1865 recordset_GetTypeInfo,
1866 recordset_GetIDsOfNames,
1867 recordset_Invoke,
1868 recordset_get_Properties,
1869 recordset_get_AbsolutePosition,
1870 recordset_put_AbsolutePosition,
1871 recordset_putref_ActiveConnection,
1872 recordset_put_ActiveConnection,
1873 recordset_get_ActiveConnection,
1874 recordset_get_BOF,
1875 recordset_get_Bookmark,
1876 recordset_put_Bookmark,
1877 recordset_get_CacheSize,
1878 recordset_put_CacheSize,
1879 recordset_get_CursorType,
1880 recordset_put_CursorType,
1881 recordset_get_EOF,
1882 recordset_get_Fields,
1883 recordset_get_LockType,
1884 recordset_put_LockType,
1885 recordset_get_MaxRecords,
1886 recordset_put_MaxRecords,
1887 recordset_get_RecordCount,
1888 recordset_putref_Source,
1889 recordset_put_Source,
1890 recordset_get_Source,
1891 recordset_AddNew,
1892 recordset_CancelUpdate,
1893 recordset_Close,
1894 recordset_Delete,
1895 recordset_GetRows,
1896 recordset_Move,
1897 recordset_MoveNext,
1898 recordset_MovePrevious,
1899 recordset_MoveFirst,
1900 recordset_MoveLast,
1901 recordset_Open,
1902 recordset_Requery,
1903 recordset__xResync,
1904 recordset_Update,
1905 recordset_get_AbsolutePage,
1906 recordset_put_AbsolutePage,
1907 recordset_get_EditMode,
1908 recordset_get_Filter,
1909 recordset_put_Filter,
1910 recordset_get_PageCount,
1911 recordset_get_PageSize,
1912 recordset_put_PageSize,
1913 recordset_get_Sort,
1914 recordset_put_Sort,
1915 recordset_get_Status,
1916 recordset_get_State,
1917 recordset__xClone,
1918 recordset_UpdateBatch,
1919 recordset_CancelBatch,
1920 recordset_get_CursorLocation,
1921 recordset_put_CursorLocation,
1922 recordset_NextRecordset,
1923 recordset_Supports,
1924 recordset_get_Collect,
1925 recordset_put_Collect,
1926 recordset_get_MarshalOptions,
1927 recordset_put_MarshalOptions,
1928 recordset_Find,
1929 recordset_Cancel,
1930 recordset_get_DataSource,
1931 recordset_putref_DataSource,
1932 recordset__xSave,
1933 recordset_get_ActiveCommand,
1934 recordset_put_StayInSync,
1935 recordset_get_StayInSync,
1936 recordset_GetString,
1937 recordset_get_DataMember,
1938 recordset_put_DataMember,
1939 recordset_CompareBookmarks,
1940 recordset_Clone,
1941 recordset_Resync,
1942 recordset_Seek,
1943 recordset_put_Index,
1944 recordset_get_Index,
1945 recordset_Save
1948 static inline struct recordset *recordset_from_ISupportErrorInfo( ISupportErrorInfo *iface )
1950 return CONTAINING_RECORD( iface, struct recordset, ISupportErrorInfo_iface );
1953 static HRESULT WINAPI recordset_supporterrorinfo_QueryInterface( ISupportErrorInfo *iface, REFIID riid, void **obj )
1955 struct recordset *recordset = recordset_from_ISupportErrorInfo( iface );
1956 return _Recordset_QueryInterface( &recordset->Recordset_iface, riid, obj );
1959 static ULONG WINAPI recordset_supporterrorinfo_AddRef( ISupportErrorInfo *iface )
1961 struct recordset *recordset = recordset_from_ISupportErrorInfo( iface );
1962 return _Recordset_AddRef( &recordset->Recordset_iface );
1965 static ULONG WINAPI recordset_supporterrorinfo_Release( ISupportErrorInfo *iface )
1967 struct recordset *recordset = recordset_from_ISupportErrorInfo( iface );
1968 return _Recordset_Release( &recordset->Recordset_iface );
1971 static HRESULT WINAPI recordset_supporterrorinfo_InterfaceSupportsErrorInfo( ISupportErrorInfo *iface, REFIID riid )
1973 struct recordset *recordset = recordset_from_ISupportErrorInfo( iface );
1974 FIXME( "%p, %s\n", recordset, debugstr_guid(riid) );
1975 return S_FALSE;
1978 static const ISupportErrorInfoVtbl recordset_supporterrorinfo_vtbl =
1980 recordset_supporterrorinfo_QueryInterface,
1981 recordset_supporterrorinfo_AddRef,
1982 recordset_supporterrorinfo_Release,
1983 recordset_supporterrorinfo_InterfaceSupportsErrorInfo
1986 static HRESULT WINAPI rsconstruction_QueryInterface(ADORecordsetConstruction *iface,
1987 REFIID riid, void **obj)
1989 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
1990 return _Recordset_QueryInterface( &recordset->Recordset_iface, riid, obj );
1993 static ULONG WINAPI rsconstruction_AddRef(ADORecordsetConstruction *iface)
1995 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
1996 return _Recordset_AddRef( &recordset->Recordset_iface );
1999 static ULONG WINAPI rsconstruction_Release(ADORecordsetConstruction *iface)
2001 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
2002 return _Recordset_Release( &recordset->Recordset_iface );
2005 static HRESULT WINAPI rsconstruction_GetTypeInfoCount(ADORecordsetConstruction *iface, UINT *pctinfo)
2007 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
2008 TRACE( "%p, %p\n", recordset, pctinfo );
2009 *pctinfo = 1;
2010 return S_OK;
2013 static HRESULT WINAPI rsconstruction_GetTypeInfo(ADORecordsetConstruction *iface, UINT iTInfo,
2014 LCID lcid, ITypeInfo **ppTInfo)
2016 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
2017 TRACE( "%p %u %lu %p\n", recordset, iTInfo, lcid, ppTInfo );
2018 return get_typeinfo(ADORecordsetConstruction_tid, ppTInfo);
2021 static HRESULT WINAPI rsconstruction_GetIDsOfNames(ADORecordsetConstruction *iface, REFIID riid,
2022 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
2024 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
2025 HRESULT hr;
2026 ITypeInfo *typeinfo;
2028 TRACE( "%p %s %p %u %lu %p\n", recordset, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId );
2030 hr = get_typeinfo(ADORecordsetConstruction_tid, &typeinfo);
2031 if(SUCCEEDED(hr))
2033 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
2034 ITypeInfo_Release(typeinfo);
2037 return hr;
2040 static HRESULT WINAPI rsconstruction_Invoke(ADORecordsetConstruction *iface, DISPID dispIdMember,
2041 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
2042 EXCEPINFO *pExcepInfo, UINT *puArgErr)
2044 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
2045 HRESULT hr;
2046 ITypeInfo *typeinfo;
2048 TRACE( "%p %ld %s %ld %d %p %p %p %p\n", recordset, dispIdMember, debugstr_guid(riid),
2049 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr );
2051 hr = get_typeinfo(ADORecordsetConstruction_tid, &typeinfo);
2052 if(SUCCEEDED(hr))
2054 hr = ITypeInfo_Invoke(typeinfo, &recordset->ADORecordsetConstruction_iface, dispIdMember, wFlags,
2055 pDispParams, pVarResult, pExcepInfo, puArgErr);
2056 ITypeInfo_Release(typeinfo);
2059 return hr;
2062 static HRESULT WINAPI rsconstruction_get_Rowset(ADORecordsetConstruction *iface, IUnknown **row_set)
2064 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
2065 HRESULT hr;
2067 TRACE( "%p, %p\n", recordset, row_set );
2069 hr = IRowset_QueryInterface(recordset->row_set, &IID_IUnknown, (void**)row_set);
2070 if ( FAILED(hr) ) return E_FAIL;
2072 return S_OK;
2075 static HRESULT WINAPI rsconstruction_put_Rowset(ADORecordsetConstruction *iface, IUnknown *unk)
2077 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
2078 HRESULT hr;
2079 IRowset *rowset;
2081 TRACE( "%p, %p\n", recordset, unk );
2083 hr = IUnknown_QueryInterface(unk, &IID_IRowset, (void**)&rowset);
2084 if ( FAILED(hr) ) return E_FAIL;
2086 if ( recordset->row_set ) IRowset_Release( recordset->row_set );
2087 recordset->row_set = rowset;
2089 return S_OK;
2092 static HRESULT WINAPI rsconstruction_get_Chapter(ADORecordsetConstruction *iface, ADO_LONGPTR *chapter)
2094 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
2095 FIXME( "%p, %p\n", recordset, chapter );
2096 return E_NOTIMPL;
2099 static HRESULT WINAPI rsconstruction_put_Chapter(ADORecordsetConstruction *iface, ADO_LONGPTR chapter)
2101 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
2102 FIXME( "%p, %Id\n", recordset, chapter );
2103 return E_NOTIMPL;
2106 static HRESULT WINAPI rsconstruction_get_RowPosition(ADORecordsetConstruction *iface, IUnknown **row_pos)
2108 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
2109 FIXME( "%p, %p\n", recordset, row_pos );
2110 return E_NOTIMPL;
2113 static HRESULT WINAPI rsconstruction_put_RowPosition(ADORecordsetConstruction *iface, IUnknown *row_pos)
2115 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
2116 FIXME( "%p, %p\n", recordset, row_pos );
2117 return E_NOTIMPL;
2120 static const ADORecordsetConstructionVtbl rsconstruction_vtbl =
2122 rsconstruction_QueryInterface,
2123 rsconstruction_AddRef,
2124 rsconstruction_Release,
2125 rsconstruction_GetTypeInfoCount,
2126 rsconstruction_GetTypeInfo,
2127 rsconstruction_GetIDsOfNames,
2128 rsconstruction_Invoke,
2129 rsconstruction_get_Rowset,
2130 rsconstruction_put_Rowset,
2131 rsconstruction_get_Chapter,
2132 rsconstruction_put_Chapter,
2133 rsconstruction_get_RowPosition,
2134 rsconstruction_put_RowPosition
2137 HRESULT Recordset_create( void **obj )
2139 struct recordset *recordset;
2141 if (!(recordset = calloc( 1, sizeof(*recordset) ))) return E_OUTOFMEMORY;
2142 recordset->Recordset_iface.lpVtbl = &recordset_vtbl;
2143 recordset->ISupportErrorInfo_iface.lpVtbl = &recordset_supporterrorinfo_vtbl;
2144 recordset->ADORecordsetConstruction_iface.lpVtbl = &rsconstruction_vtbl;
2145 recordset->refs = 1;
2146 recordset->index = -1;
2147 recordset->cursor_location = adUseServer;
2148 recordset->cursor_type = adOpenForwardOnly;
2149 recordset->row_set = NULL;
2150 recordset->editmode = adEditNone;
2151 VariantInit( &recordset->filter );
2153 *obj = &recordset->Recordset_iface;
2154 TRACE( "returning iface %p\n", *obj );
2155 return S_OK;