mfmediaengine: Remove unnecessary import library.
[wine.git] / dlls / msado15 / recordset.c
blob23865b37688972f831c20ece447d87e9315b4e19
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 Properties Properties_iface;
69 LONG refs;
70 WCHAR *name;
71 DataTypeEnum type;
72 LONG defined_size;
73 LONG attrs;
74 LONG index;
75 struct recordset *recordset;
78 static inline struct field *impl_from_Field( Field *iface )
80 return CONTAINING_RECORD( iface, struct field, Field_iface );
83 static inline struct field *impl_from_Properties( Properties *iface )
85 return CONTAINING_RECORD( iface, struct field, Properties_iface );
88 static ULONG WINAPI field_AddRef( Field *iface )
90 struct field *field = impl_from_Field( iface );
91 LONG refs = InterlockedIncrement( &field->refs );
92 TRACE( "%p new refcount %d\n", field, refs );
93 return refs;
96 static ULONG WINAPI field_Release( Field *iface )
98 struct field *field = impl_from_Field( iface );
99 LONG refs = InterlockedDecrement( &field->refs );
100 TRACE( "%p new refcount %d\n", field, refs );
101 if (!refs)
103 TRACE( "destroying %p\n", field );
104 heap_free( field->name );
105 heap_free( field );
107 return refs;
110 static HRESULT WINAPI field_QueryInterface( Field *iface, REFIID riid, void **obj )
112 struct field *field = impl_from_Field( iface );
113 TRACE( "%p, %s, %p\n", iface, debugstr_guid(riid), obj );
115 if (IsEqualGUID( riid, &IID_Field ) || IsEqualGUID( riid, &IID_IDispatch ) ||
116 IsEqualGUID( riid, &IID_IUnknown ))
118 *obj = iface;
120 else if (IsEqualGUID( riid, &IID_ISupportErrorInfo ))
122 *obj = &field->ISupportErrorInfo_iface;
124 else
126 FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
127 return E_NOINTERFACE;
129 field_AddRef( iface );
130 return S_OK;
133 static HRESULT WINAPI field_GetTypeInfoCount( Field *iface, UINT *count )
135 struct field *field = impl_from_Field( iface );
136 TRACE( "%p, %p\n", field, count );
137 *count = 1;
138 return S_OK;
141 static HRESULT WINAPI field_GetTypeInfo( Field *iface, UINT index, LCID lcid, ITypeInfo **info )
143 struct field *field = impl_from_Field( iface );
144 TRACE( "%p, %u, %u, %p\n", field, index, lcid, info );
145 return get_typeinfo(Field_tid, info);
148 static HRESULT WINAPI field_GetIDsOfNames( Field *iface, REFIID riid, LPOLESTR *names, UINT count,
149 LCID lcid, DISPID *dispid )
151 struct field *field = impl_from_Field( iface );
152 HRESULT hr;
153 ITypeInfo *typeinfo;
155 TRACE( "%p, %s, %p, %u, %u, %p\n", field, debugstr_guid(riid), names, count, lcid, dispid );
157 hr = get_typeinfo(Field_tid, &typeinfo);
158 if(SUCCEEDED(hr))
160 hr = ITypeInfo_GetIDsOfNames(typeinfo, names, count, dispid);
161 ITypeInfo_Release(typeinfo);
164 return hr;
167 static HRESULT WINAPI field_Invoke( Field *iface, DISPID member, REFIID riid, LCID lcid, WORD flags,
168 DISPPARAMS *params, VARIANT *result, EXCEPINFO *excep_info, UINT *arg_err )
170 struct field *field = impl_from_Field( iface );
171 HRESULT hr;
172 ITypeInfo *typeinfo;
174 TRACE( "%p, %d, %s, %d, %d, %p, %p, %p, %p\n", field, member, debugstr_guid(riid), lcid, flags, params,
175 result, excep_info, arg_err );
177 hr = get_typeinfo(Field_tid, &typeinfo);
178 if(SUCCEEDED(hr))
180 hr = ITypeInfo_Invoke(typeinfo, &field->Field_iface, member, flags, params,
181 result, excep_info, arg_err);
182 ITypeInfo_Release(typeinfo);
185 return hr;
188 static HRESULT WINAPI field_get_Properties( Field *iface, Properties **obj )
190 struct field *field = impl_from_Field( iface );
191 TRACE( "%p, %p\n", iface, obj );
193 *obj = &field->Properties_iface;
194 Properties_AddRef(&field->Properties_iface);
195 return S_OK;
198 static HRESULT WINAPI field_get_ActualSize( Field *iface, LONG *size )
200 FIXME( "%p, %p\n", iface, size );
201 return E_NOTIMPL;
204 static HRESULT WINAPI field_get_Attributes( Field *iface, LONG *attrs )
206 struct field *field = impl_from_Field( iface );
208 TRACE( "%p, %p\n", field, attrs );
210 *attrs = field->attrs;
211 return S_OK;
214 static HRESULT WINAPI field_get_DefinedSize( Field *iface, LONG *size )
216 struct field *field = impl_from_Field( iface );
218 TRACE( "%p, %p\n", field, size );
220 *size = field->defined_size;
221 return S_OK;
224 static HRESULT WINAPI field_get_Name( Field *iface, BSTR *str )
226 struct field *field = impl_from_Field( iface );
227 BSTR name;
229 TRACE( "%p, %p\n", field, str );
231 if (!(name = SysAllocString( field->name ))) return E_OUTOFMEMORY;
232 *str = name;
233 return S_OK;
236 static HRESULT WINAPI field_get_Type( Field *iface, DataTypeEnum *type )
238 struct field *field = impl_from_Field( iface );
240 TRACE( "%p, %p\n", field, type );
242 *type = field->type;
243 return S_OK;
246 static LONG get_column_count( struct recordset *recordset )
248 return recordset->fields->count;
251 static HRESULT WINAPI field_get_Value( Field *iface, VARIANT *val )
253 struct field *field = impl_from_Field( iface );
254 ULONG row = field->recordset->index, col = field->index, col_count;
255 VARIANT copy;
256 HRESULT hr;
258 TRACE( "%p, %p\n", field, val );
260 if (field->recordset->state == adStateClosed) return MAKE_ADO_HRESULT( adErrObjectClosed );
261 if (field->recordset->index < 0) return MAKE_ADO_HRESULT( adErrNoCurrentRecord );
263 col_count = get_column_count( field->recordset );
265 VariantInit( &copy );
266 if ((hr = VariantCopy( &copy, &field->recordset->data[row * col_count + col] )) != S_OK) return hr;
268 *val = copy;
269 return S_OK;
272 static HRESULT WINAPI field_put_Value( Field *iface, VARIANT val )
274 struct field *field = impl_from_Field( iface );
275 ULONG row = field->recordset->index, col = field->index, col_count;
276 VARIANT copy;
277 HRESULT hr;
279 TRACE( "%p, %s\n", field, debugstr_variant(&val) );
281 if (field->recordset->state == adStateClosed) return MAKE_ADO_HRESULT( adErrObjectClosed );
282 if (field->recordset->index < 0) return MAKE_ADO_HRESULT( adErrNoCurrentRecord );
284 col_count = get_column_count( field->recordset );
286 VariantInit( &copy );
287 if ((hr = VariantCopy( &copy, &val )) != S_OK) return hr;
289 field->recordset->data[row * col_count + col] = copy;
290 return S_OK;
293 static HRESULT WINAPI field_get_Precision( Field *iface, unsigned char *precision )
295 FIXME( "%p, %p\n", iface, precision );
296 return E_NOTIMPL;
299 static HRESULT WINAPI field_get_NumericScale( Field *iface, unsigned char *scale )
301 FIXME( "%p, %p\n", iface, scale );
302 return E_NOTIMPL;
305 static HRESULT WINAPI field_AppendChunk( Field *iface, VARIANT data )
307 FIXME( "%p, %s\n", iface, debugstr_variant(&data) );
308 return E_NOTIMPL;
311 static HRESULT WINAPI field_GetChunk( Field *iface, LONG length, VARIANT *var )
313 FIXME( "%p, %d, %p\n", iface, length, var );
314 return E_NOTIMPL;
317 static HRESULT WINAPI field_get_OriginalValue( Field *iface, VARIANT *val )
319 FIXME( "%p, %p\n", iface, val );
320 return E_NOTIMPL;
323 static HRESULT WINAPI field_get_UnderlyingValue( Field *iface, VARIANT *val )
325 FIXME( "%p, %p\n", iface, val );
326 return E_NOTIMPL;
329 static HRESULT WINAPI field_get_DataFormat( Field *iface, IUnknown **format )
331 FIXME( "%p, %p\n", iface, format );
332 return E_NOTIMPL;
335 static HRESULT WINAPI field_putref_DataFormat( Field *iface, IUnknown *format )
337 FIXME( "%p, %p\n", iface, format );
338 return E_NOTIMPL;
341 static HRESULT WINAPI field_put_Precision( Field *iface, unsigned char precision )
343 FIXME( "%p, %c\n", iface, precision );
344 return E_NOTIMPL;
347 static HRESULT WINAPI field_put_NumericScale( Field *iface, unsigned char scale )
349 FIXME( "%p, %c\n", iface, scale );
350 return E_NOTIMPL;
353 static HRESULT WINAPI field_put_Type( Field *iface, DataTypeEnum type )
355 struct field *field = impl_from_Field( iface );
357 TRACE( "%p, %u\n", field, type );
359 field->type = type;
360 return S_OK;
363 static HRESULT WINAPI field_put_DefinedSize( Field *iface, LONG size )
365 struct field *field = impl_from_Field( iface );
367 TRACE( "%p, %d\n", field, size );
369 field->defined_size = size;
370 return S_OK;
373 static HRESULT WINAPI field_put_Attributes( Field *iface, LONG attrs )
375 struct field *field = impl_from_Field( iface );
377 TRACE( "%p, %d\n", field, attrs );
379 field->attrs = attrs;
380 return S_OK;
383 static HRESULT WINAPI field_get_Status( Field *iface, LONG *status )
385 FIXME( "%p, %p\n", iface, status );
386 return E_NOTIMPL;
389 static const struct FieldVtbl field_vtbl =
391 field_QueryInterface,
392 field_AddRef,
393 field_Release,
394 field_GetTypeInfoCount,
395 field_GetTypeInfo,
396 field_GetIDsOfNames,
397 field_Invoke,
398 field_get_Properties,
399 field_get_ActualSize,
400 field_get_Attributes,
401 field_get_DefinedSize,
402 field_get_Name,
403 field_get_Type,
404 field_get_Value,
405 field_put_Value,
406 field_get_Precision,
407 field_get_NumericScale,
408 field_AppendChunk,
409 field_GetChunk,
410 field_get_OriginalValue,
411 field_get_UnderlyingValue,
412 field_get_DataFormat,
413 field_putref_DataFormat,
414 field_put_Precision,
415 field_put_NumericScale,
416 field_put_Type,
417 field_put_DefinedSize,
418 field_put_Attributes,
419 field_get_Status
422 static inline struct field *field_from_ISupportErrorInfo( ISupportErrorInfo *iface )
424 return CONTAINING_RECORD( iface, struct field, ISupportErrorInfo_iface );
427 static HRESULT WINAPI field_supporterrorinfo_QueryInterface( ISupportErrorInfo *iface, REFIID riid, void **obj )
429 struct field *field = field_from_ISupportErrorInfo( iface );
430 return Field_QueryInterface( &field->Field_iface, riid, obj );
433 static ULONG WINAPI field_supporterrorinfo_AddRef( ISupportErrorInfo *iface )
435 struct field *field = field_from_ISupportErrorInfo( iface );
436 return Field_AddRef( &field->Field_iface );
439 static ULONG WINAPI field_supporterrorinfo_Release( ISupportErrorInfo *iface )
441 struct field *field = field_from_ISupportErrorInfo( iface );
442 return Field_Release( &field->Field_iface );
445 static HRESULT WINAPI field_supporterrorinfo_InterfaceSupportsErrorInfo( ISupportErrorInfo *iface, REFIID riid )
447 struct field *field = field_from_ISupportErrorInfo( iface );
448 FIXME( "%p, %s\n", field, debugstr_guid(riid) );
449 return S_FALSE;
452 static const ISupportErrorInfoVtbl field_supporterrorinfo_vtbl =
454 field_supporterrorinfo_QueryInterface,
455 field_supporterrorinfo_AddRef,
456 field_supporterrorinfo_Release,
457 field_supporterrorinfo_InterfaceSupportsErrorInfo
460 static HRESULT WINAPI field_props_QueryInterface(Properties *iface, REFIID riid, void **ppv)
462 struct field *field = impl_from_Properties( iface );
464 if (IsEqualGUID( riid, &IID_Properties) || IsEqualGUID( riid, &IID_IDispatch ) ||
465 IsEqualGUID( riid, &IID_IUnknown ))
467 *ppv = &field->Properties_iface;
469 else
471 FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
472 return E_NOINTERFACE;
474 Field_AddRef(&field->Field_iface);
475 return S_OK;
478 static ULONG WINAPI field_props_AddRef(Properties *iface)
480 struct field *field = impl_from_Properties( iface );
481 return Field_AddRef(&field->Field_iface);
484 static ULONG WINAPI field_props_Release(Properties *iface)
486 struct field *field = impl_from_Properties( iface );
487 return Field_Release(&field->Field_iface);
490 static HRESULT WINAPI field_props_GetTypeInfoCount(Properties *iface, UINT *count)
492 struct field *field = impl_from_Properties( iface );
493 TRACE( "%p, %p\n", field, count );
494 *count = 1;
495 return S_OK;
498 static HRESULT WINAPI field_props_GetTypeInfo(Properties *iface, UINT index, LCID lcid, ITypeInfo **info)
500 struct field *field = impl_from_Properties( iface );
501 TRACE( "%p, %u, %u, %p\n", field, index, lcid, info );
502 return get_typeinfo(Properties_tid, info);
505 static HRESULT WINAPI field_props_GetIDsOfNames(Properties *iface, REFIID riid, LPOLESTR *names, UINT count,
506 LCID lcid, DISPID *dispid )
508 struct field *field = impl_from_Properties( iface );
509 HRESULT hr;
510 ITypeInfo *typeinfo;
512 TRACE( "%p, %s, %p, %u, %u, %p\n", field, debugstr_guid(riid), names, count, lcid, dispid );
514 hr = get_typeinfo(Properties_tid, &typeinfo);
515 if(SUCCEEDED(hr))
517 hr = ITypeInfo_GetIDsOfNames(typeinfo, names, count, dispid);
518 ITypeInfo_Release(typeinfo);
521 return hr;
524 static HRESULT WINAPI field_props_Invoke(Properties *iface, DISPID member, REFIID riid, LCID lcid, WORD flags,
525 DISPPARAMS *params, VARIANT *result, EXCEPINFO *excep_info, UINT *arg_err )
527 struct field *field = impl_from_Properties( iface );
528 HRESULT hr;
529 ITypeInfo *typeinfo;
531 TRACE( "%p, %d, %s, %d, %d, %p, %p, %p, %p\n", field, member, debugstr_guid(riid), lcid, flags, params,
532 result, excep_info, arg_err );
534 hr = get_typeinfo(Properties_tid, &typeinfo);
535 if(SUCCEEDED(hr))
537 hr = ITypeInfo_Invoke(typeinfo, &field->Field_iface, member, flags, params,
538 result, excep_info, arg_err);
539 ITypeInfo_Release(typeinfo);
542 return hr;
545 static HRESULT WINAPI field_props_get_Count(Properties *iface, LONG *count)
547 struct field *field = impl_from_Properties( iface );
548 FIXME( "%p, %p\n", field, count);
549 *count = 0;
550 return S_OK;
553 static HRESULT WINAPI field_props__NewEnum(Properties *iface, IUnknown **object)
555 struct field *field = impl_from_Properties( iface );
556 FIXME( "%p, %p\n", field, object);
557 return E_NOTIMPL;
560 static HRESULT WINAPI field_props_Refresh(Properties *iface)
562 struct field *field = impl_from_Properties( iface );
563 FIXME( "%p\n", field);
564 return E_NOTIMPL;
567 static HRESULT WINAPI field_props_get_Item(Properties *iface, VARIANT index, Property **object)
569 struct field *field = impl_from_Properties( iface );
570 FIXME( "%p, %s, %p\n", field, debugstr_variant(&index), object);
571 return MAKE_ADO_HRESULT(adErrItemNotFound);
574 static struct PropertiesVtbl field_properties_vtbl =
576 field_props_QueryInterface,
577 field_props_AddRef,
578 field_props_Release,
579 field_props_GetTypeInfoCount,
580 field_props_GetTypeInfo,
581 field_props_GetIDsOfNames,
582 field_props_Invoke,
583 field_props_get_Count,
584 field_props__NewEnum,
585 field_props_Refresh,
586 field_props_get_Item
589 static HRESULT Field_create( const WCHAR *name, LONG index, struct recordset *recordset, Field **obj )
591 struct field *field;
593 if (!(field = heap_alloc_zero( sizeof(*field) ))) return E_OUTOFMEMORY;
594 field->Field_iface.lpVtbl = &field_vtbl;
595 field->ISupportErrorInfo_iface.lpVtbl = &field_supporterrorinfo_vtbl;
596 field->Properties_iface.lpVtbl = &field_properties_vtbl;
597 field->refs = 1;
598 if (!(field->name = strdupW( name )))
600 heap_free( field );
601 return E_OUTOFMEMORY;
603 field->index = index;
604 field->recordset = recordset;
606 *obj = &field->Field_iface;
607 TRACE( "returning iface %p\n", *obj );
608 return S_OK;
611 static inline struct fields *impl_from_Fields( Fields *iface )
613 return CONTAINING_RECORD( iface, struct fields, Fields_iface );
616 static ULONG WINAPI fields_AddRef( Fields *iface )
618 struct fields *fields = impl_from_Fields( iface );
619 LONG refs = InterlockedIncrement( &fields->refs );
620 TRACE( "%p new refcount %d\n", fields, refs );
621 return refs;
624 static ULONG WINAPI fields_Release( Fields *iface )
626 struct fields *fields = impl_from_Fields( iface );
627 LONG refs = InterlockedDecrement( &fields->refs );
628 TRACE( "%p new refcount %d\n", fields, refs );
629 if (!refs)
631 if (fields->recordset) _Recordset_Release( &fields->recordset->Recordset_iface );
632 fields->recordset = NULL;
633 WARN( "not destroying %p\n", fields );
634 return InterlockedIncrement( &fields->refs );
636 return refs;
639 static HRESULT WINAPI fields_QueryInterface( Fields *iface, REFIID riid, void **obj )
641 struct fields *fields = impl_from_Fields( iface );
642 TRACE( "%p, %s, %p\n", iface, debugstr_guid(riid), obj );
644 if (IsEqualGUID( riid, &IID_Fields ) || IsEqualGUID( riid, &IID_IDispatch ) ||
645 IsEqualGUID( riid, &IID_IUnknown ))
647 *obj = iface;
649 else if (IsEqualGUID( riid, &IID_ISupportErrorInfo ))
651 *obj = &fields->ISupportErrorInfo_iface;
653 else
655 FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
656 return E_NOINTERFACE;
658 fields_AddRef( iface );
659 return S_OK;
662 static HRESULT WINAPI fields_GetTypeInfoCount( Fields *iface, UINT *count )
664 struct fields *fields = impl_from_Fields( iface );
665 TRACE( "%p, %p\n", fields, count );
666 *count = 1;
667 return S_OK;
670 static HRESULT WINAPI fields_GetTypeInfo( Fields *iface, UINT index, LCID lcid, ITypeInfo **info )
672 struct fields *fields = impl_from_Fields( iface );
673 TRACE( "%p, %u, %u, %p\n", fields, index, lcid, info );
674 return get_typeinfo(Fields_tid, info);
677 static HRESULT WINAPI fields_GetIDsOfNames( Fields *iface, REFIID riid, LPOLESTR *names, UINT count,
678 LCID lcid, DISPID *dispid )
680 struct fields *fields = impl_from_Fields( iface );
681 HRESULT hr;
682 ITypeInfo *typeinfo;
684 TRACE( "%p, %s, %p, %u, %u, %p\n", fields, debugstr_guid(riid), names, count, lcid, dispid );
686 hr = get_typeinfo(Fields_tid, &typeinfo);
687 if(SUCCEEDED(hr))
689 hr = ITypeInfo_GetIDsOfNames(typeinfo, names, count, dispid);
690 ITypeInfo_Release(typeinfo);
693 return hr;
696 static HRESULT WINAPI fields_Invoke( Fields *iface, DISPID member, REFIID riid, LCID lcid, WORD flags,
697 DISPPARAMS *params, VARIANT *result, EXCEPINFO *excep_info, UINT *arg_err )
699 struct fields *fields = impl_from_Fields( iface );
700 HRESULT hr;
701 ITypeInfo *typeinfo;
703 TRACE( "%p, %d, %s, %d, %d, %p, %p, %p, %p\n", fields, member, debugstr_guid(riid), lcid, flags, params,
704 result, excep_info, arg_err );
706 hr = get_typeinfo(Fields_tid, &typeinfo);
707 if(SUCCEEDED(hr))
709 hr = ITypeInfo_Invoke(typeinfo, &fields->Fields_iface, member, flags, params,
710 result, excep_info, arg_err);
711 ITypeInfo_Release(typeinfo);
714 return hr;
717 static HRESULT WINAPI fields_get_Count( Fields *iface, LONG *count )
719 struct fields *fields = impl_from_Fields( iface );
721 TRACE( "%p, %p\n", fields, count );
723 *count = fields->count;
724 return S_OK;
727 static HRESULT WINAPI fields__NewEnum( Fields *iface, IUnknown **obj )
729 FIXME( "%p, %p\n", iface, obj );
730 return E_NOTIMPL;
733 static HRESULT WINAPI fields_Refresh( Fields *iface )
735 FIXME( "%p\n", iface );
736 return E_NOTIMPL;
739 static HRESULT map_index( struct fields *fields, VARIANT *index, ULONG *ret )
741 ULONG i;
743 if (V_VT( index ) != VT_BSTR)
745 VARIANT idx;
747 VariantInit(&idx);
748 if (VariantChangeType(&idx, index, 0, VT_UI4) == S_OK)
750 i = V_UI4 ( &idx );
751 if (i < fields->count)
753 *ret = i;
754 return S_OK;
758 return MAKE_ADO_HRESULT(adErrItemNotFound);
761 for (i = 0; i < fields->count; i++)
763 BSTR name;
764 BOOL match;
765 HRESULT hr;
767 if ((hr = Field_get_Name( fields->field[i], &name )) != S_OK) return hr;
768 match = !wcsicmp( V_BSTR( index ), name );
769 SysFreeString( name );
770 if (match)
772 *ret = i;
773 return S_OK;
777 return MAKE_ADO_HRESULT(adErrItemNotFound);
780 static HRESULT WINAPI fields_get_Item( Fields *iface, VARIANT index, Field **obj )
782 struct fields *fields = impl_from_Fields( iface );
783 HRESULT hr;
784 ULONG i;
786 TRACE( "%p, %s, %p\n", fields, debugstr_variant(&index), obj );
788 if ((hr = map_index( fields, &index, &i )) != S_OK) return hr;
790 Field_AddRef( fields->field[i] );
791 *obj = fields->field[i];
792 return S_OK;
795 static BOOL resize_fields( struct fields *fields, ULONG count )
797 if (count > fields->allocated)
799 Field **tmp;
800 ULONG new_size = max( count, fields->allocated * 2 );
801 if (!(tmp = heap_realloc( fields->field, new_size * sizeof(*tmp) ))) return FALSE;
802 fields->field = tmp;
803 fields->allocated = new_size;
806 fields->count = count;
807 return TRUE;
810 static HRESULT append_field( struct fields *fields, BSTR name, DataTypeEnum type, LONG size, FieldAttributeEnum attr,
811 VARIANT *value )
813 Field *field;
814 HRESULT hr;
816 if ((hr = Field_create( name, fields->count, fields->recordset, &field )) != S_OK) return hr;
817 Field_put_Type( field, type );
818 Field_put_DefinedSize( field, size );
819 if (attr != adFldUnspecified) Field_put_Attributes( field, attr );
820 if (value) FIXME( "ignoring value %s\n", debugstr_variant(value) );
822 if (!(resize_fields( fields, fields->count + 1 )))
824 Field_Release( field );
825 return E_OUTOFMEMORY;
828 fields->field[fields->count - 1] = field;
829 return S_OK;
832 static HRESULT WINAPI fields__Append( Fields *iface, BSTR name, DataTypeEnum type, LONG size, FieldAttributeEnum attr )
834 struct fields *fields = impl_from_Fields( iface );
836 TRACE( "%p, %s, %u, %d, %d\n", fields, debugstr_w(name), type, size, attr );
838 return append_field( fields, name, type, size, attr, NULL );
841 static HRESULT WINAPI fields_Delete( Fields *iface, VARIANT index )
843 FIXME( "%p, %s\n", iface, debugstr_variant(&index) );
844 return E_NOTIMPL;
847 static HRESULT WINAPI fields_Append( Fields *iface, BSTR name, DataTypeEnum type, LONG size, FieldAttributeEnum attr,
848 VARIANT value )
850 struct fields *fields = impl_from_Fields( iface );
852 TRACE( "%p, %s, %u, %d, %d, %s\n", fields, debugstr_w(name), type, size, attr, debugstr_variant(&value) );
854 return append_field( fields, name, type, size, attr, &value );
857 static HRESULT WINAPI fields_Update( Fields *iface )
859 FIXME( "%p\n", iface );
860 return E_NOTIMPL;
863 static HRESULT WINAPI fields_Resync( Fields *iface, ResyncEnum resync_values )
865 FIXME( "%p, %u\n", iface, resync_values );
866 return E_NOTIMPL;
869 static HRESULT WINAPI fields_CancelUpdate( Fields *iface )
871 FIXME( "%p\n", iface );
872 return E_NOTIMPL;
875 static const struct FieldsVtbl fields_vtbl =
877 fields_QueryInterface,
878 fields_AddRef,
879 fields_Release,
880 fields_GetTypeInfoCount,
881 fields_GetTypeInfo,
882 fields_GetIDsOfNames,
883 fields_Invoke,
884 fields_get_Count,
885 fields__NewEnum,
886 fields_Refresh,
887 fields_get_Item,
888 fields__Append,
889 fields_Delete,
890 fields_Append,
891 fields_Update,
892 fields_Resync,
893 fields_CancelUpdate
896 static inline struct fields *fields_from_ISupportErrorInfo( ISupportErrorInfo *iface )
898 return CONTAINING_RECORD( iface, struct fields, ISupportErrorInfo_iface );
901 static HRESULT WINAPI fields_supporterrorinfo_QueryInterface( ISupportErrorInfo *iface, REFIID riid, void **obj )
903 struct fields *fields = fields_from_ISupportErrorInfo( iface );
904 return Fields_QueryInterface( &fields->Fields_iface, riid, obj );
907 static ULONG WINAPI fields_supporterrorinfo_AddRef( ISupportErrorInfo *iface )
909 struct fields *fields = fields_from_ISupportErrorInfo( iface );
910 return Fields_AddRef( &fields->Fields_iface );
913 static ULONG WINAPI fields_supporterrorinfo_Release( ISupportErrorInfo *iface )
915 struct fields *fields = fields_from_ISupportErrorInfo( iface );
916 return Fields_Release( &fields->Fields_iface );
919 static HRESULT WINAPI fields_supporterrorinfo_InterfaceSupportsErrorInfo( ISupportErrorInfo *iface, REFIID riid )
921 struct fields *fields = fields_from_ISupportErrorInfo( iface );
922 FIXME( "%p, %s\n", fields, debugstr_guid(riid) );
923 return S_FALSE;
926 static const ISupportErrorInfoVtbl fields_supporterrorinfo_vtbl =
928 fields_supporterrorinfo_QueryInterface,
929 fields_supporterrorinfo_AddRef,
930 fields_supporterrorinfo_Release,
931 fields_supporterrorinfo_InterfaceSupportsErrorInfo
934 static void map_rowset_fields(struct recordset *recordset, struct fields *fields)
936 HRESULT hr;
937 IColumnsInfo *columninfo;
938 DBORDINAL columns, i;
939 DBCOLUMNINFO *colinfo;
940 OLECHAR *stringsbuffer;
942 /* Not Finding the interface or GetColumnInfo failing just causes 0 Fields to be returned */
943 hr = IRowset_QueryInterface(recordset->row_set, &IID_IColumnsInfo, (void**)&columninfo);
944 if (FAILED(hr))
945 return;
947 hr = IColumnsInfo_GetColumnInfo(columninfo, &columns, &colinfo, &stringsbuffer);
948 if (SUCCEEDED(hr))
950 for (i=0; i < columns; i++)
952 TRACE("Adding Column %lu, pwszName: %s, pTypeInfo %p, iOrdinal %lu, dwFlags 0x%08x, "
953 "ulColumnSize %lu, wType %d, bPrecision %d, bScale %d\n",
954 i, debugstr_w(colinfo[i].pwszName), colinfo[i].pTypeInfo, colinfo[i].iOrdinal,
955 colinfo[i].dwFlags, colinfo[i].ulColumnSize, colinfo[i].wType,
956 colinfo[i].bPrecision, colinfo[i].bScale);
958 hr = append_field(fields, colinfo[i].pwszName, colinfo[i].wType, colinfo[i].ulColumnSize,
959 colinfo[i].dwFlags, NULL);
960 if (FAILED(hr))
962 ERR("Failed to add Field name - 0x%08x\n", hr);
963 return;
967 CoTaskMemFree(colinfo);
968 CoTaskMemFree(stringsbuffer);
971 IColumnsInfo_Release(columninfo);
974 static HRESULT fields_create( struct recordset *recordset, struct fields **ret )
976 struct fields *fields;
978 if (!(fields = heap_alloc_zero( sizeof(*fields) ))) return E_OUTOFMEMORY;
979 fields->Fields_iface.lpVtbl = &fields_vtbl;
980 fields->ISupportErrorInfo_iface.lpVtbl = &fields_supporterrorinfo_vtbl;
981 fields->refs = 1;
982 fields->recordset = recordset;
983 _Recordset_AddRef( &fields->recordset->Recordset_iface );
985 if ( recordset->row_set )
986 map_rowset_fields(recordset, fields);
988 *ret = fields;
989 TRACE( "returning %p\n", *ret );
990 return S_OK;
993 static inline struct recordset *impl_from_Recordset( _Recordset *iface )
995 return CONTAINING_RECORD( iface, struct recordset, Recordset_iface );
998 static inline struct recordset *impl_from_ADORecordsetConstruction( ADORecordsetConstruction *iface )
1000 return CONTAINING_RECORD( iface, struct recordset, ADORecordsetConstruction_iface );
1003 static ULONG WINAPI recordset_AddRef( _Recordset *iface )
1005 struct recordset *recordset = impl_from_Recordset( iface );
1006 LONG refs = InterlockedIncrement( &recordset->refs );
1007 TRACE( "%p new refcount %d\n", recordset, refs );
1008 return refs;
1011 static void close_recordset( struct recordset *recordset )
1013 ULONG row, col, col_count;
1014 ULONG i;
1016 if ( recordset->row_set ) IRowset_Release( recordset->row_set );
1017 recordset->row_set = NULL;
1019 if (!recordset->fields) return;
1020 col_count = get_column_count( recordset );
1022 for (i = 0; i < col_count; i++)
1024 struct field *field = impl_from_Field( recordset->fields->field[i] );
1025 field->recordset = NULL;
1026 Field_Release(&field->Field_iface);
1028 recordset->fields->count = 0;
1029 Fields_Release( &recordset->fields->Fields_iface );
1030 recordset->fields = NULL;
1032 for (row = 0; row < recordset->count; row++)
1033 for (col = 0; col < col_count; col++) VariantClear( &recordset->data[row * col_count + col] );
1035 recordset->count = recordset->allocated = recordset->index = 0;
1036 heap_free( recordset->data );
1037 recordset->data = NULL;
1040 static ULONG WINAPI recordset_Release( _Recordset *iface )
1042 struct recordset *recordset = impl_from_Recordset( iface );
1043 LONG refs = InterlockedDecrement( &recordset->refs );
1044 TRACE( "%p new refcount %d\n", recordset, refs );
1045 if (!refs)
1047 TRACE( "destroying %p\n", recordset );
1048 close_recordset( recordset );
1049 heap_free( recordset );
1051 return refs;
1054 static HRESULT WINAPI recordset_QueryInterface( _Recordset *iface, REFIID riid, void **obj )
1056 struct recordset *recordset = impl_from_Recordset( iface );
1057 TRACE( "%p, %s, %p\n", iface, debugstr_guid(riid), obj );
1059 *obj = NULL;
1061 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch) ||
1062 IsEqualIID(riid, &IID__ADO) || IsEqualIID(riid, &IID_Recordset15) ||
1063 IsEqualIID(riid, &IID_Recordset20) || IsEqualIID(riid, &IID_Recordset21) ||
1064 IsEqualIID(riid, &IID__Recordset))
1066 *obj = iface;
1068 else if (IsEqualGUID( riid, &IID_ISupportErrorInfo ))
1070 *obj = &recordset->ISupportErrorInfo_iface;
1072 else if (IsEqualGUID( riid, &IID_ADORecordsetConstruction ))
1074 *obj = &recordset->ADORecordsetConstruction_iface;
1076 else if (IsEqualGUID( riid, &IID_IRunnableObject ))
1078 TRACE("IID_IRunnableObject not supported returning NULL\n");
1079 return E_NOINTERFACE;
1081 else
1083 FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
1084 return E_NOINTERFACE;
1086 recordset_AddRef( iface );
1087 return S_OK;
1090 static HRESULT WINAPI recordset_GetTypeInfoCount( _Recordset *iface, UINT *count )
1092 struct recordset *recordset = impl_from_Recordset( iface );
1093 TRACE( "%p, %p\n", recordset, count );
1094 *count = 1;
1095 return S_OK;
1098 static HRESULT WINAPI recordset_GetTypeInfo( _Recordset *iface, UINT index, LCID lcid, ITypeInfo **info )
1100 struct recordset *recordset = impl_from_Recordset( iface );
1101 TRACE( "%p, %u, %u, %p\n", recordset, index, lcid, info );
1102 return get_typeinfo(Recordset_tid, info);
1105 static HRESULT WINAPI recordset_GetIDsOfNames( _Recordset *iface, REFIID riid, LPOLESTR *names, UINT count,
1106 LCID lcid, DISPID *dispid )
1108 struct recordset *recordset = impl_from_Recordset( iface );
1109 HRESULT hr;
1110 ITypeInfo *typeinfo;
1112 TRACE( "%p, %s, %p, %u, %u, %p\n", recordset, debugstr_guid(riid), names, count, lcid, dispid );
1114 hr = get_typeinfo(Recordset_tid, &typeinfo);
1115 if(SUCCEEDED(hr))
1117 hr = ITypeInfo_GetIDsOfNames(typeinfo, names, count, dispid);
1118 ITypeInfo_Release(typeinfo);
1121 return hr;
1124 static HRESULT WINAPI recordset_Invoke( _Recordset *iface, DISPID member, REFIID riid, LCID lcid, WORD flags,
1125 DISPPARAMS *params, VARIANT *result, EXCEPINFO *excep_info, UINT *arg_err )
1127 struct recordset *recordset = impl_from_Recordset( iface );
1128 HRESULT hr;
1129 ITypeInfo *typeinfo;
1131 TRACE( "%p, %d, %s, %d, %d, %p, %p, %p, %p\n", recordset, member, debugstr_guid(riid), lcid, flags, params,
1132 result, excep_info, arg_err );
1134 hr = get_typeinfo(Recordset_tid, &typeinfo);
1135 if(SUCCEEDED(hr))
1137 hr = ITypeInfo_Invoke(typeinfo, &recordset->Recordset_iface, member, flags, params,
1138 result, excep_info, arg_err);
1139 ITypeInfo_Release(typeinfo);
1142 return hr;
1145 static HRESULT WINAPI recordset_get_Properties( _Recordset *iface, Properties **obj )
1147 FIXME( "%p, %p\n", iface, obj );
1148 return E_NOTIMPL;
1151 static HRESULT WINAPI recordset_get_AbsolutePosition( _Recordset *iface, PositionEnum_Param *pos )
1153 FIXME( "%p, %p\n", iface, pos );
1154 return E_NOTIMPL;
1157 static HRESULT WINAPI recordset_put_AbsolutePosition( _Recordset *iface, PositionEnum_Param pos )
1159 FIXME( "%p, %d\n", iface, pos );
1160 return E_NOTIMPL;
1163 static HRESULT WINAPI recordset_putref_ActiveConnection( _Recordset *iface, IDispatch *connection )
1165 FIXME( "%p, %p\n", iface, connection );
1166 return E_NOTIMPL;
1169 static HRESULT WINAPI recordset_put_ActiveConnection( _Recordset *iface, VARIANT connection )
1171 FIXME( "%p, %s\n", iface, debugstr_variant(&connection) );
1172 return E_NOTIMPL;
1175 static HRESULT WINAPI recordset_get_ActiveConnection( _Recordset *iface, VARIANT *connection )
1177 FIXME( "%p, %p\n", iface, connection );
1178 return E_NOTIMPL;
1181 static HRESULT WINAPI recordset_get_BOF( _Recordset *iface, VARIANT_BOOL *bof )
1183 struct recordset *recordset = impl_from_Recordset( iface );
1185 TRACE( "%p, %p\n", recordset, bof );
1187 *bof = (recordset->index < 0) ? VARIANT_TRUE : VARIANT_FALSE;
1188 return S_OK;
1191 static HRESULT WINAPI recordset_get_Bookmark( _Recordset *iface, VARIANT *bookmark )
1193 struct recordset *recordset = impl_from_Recordset( iface );
1194 TRACE( "%p, %p\n", iface, bookmark );
1196 if (recordset->state == adStateClosed) return MAKE_ADO_HRESULT( adErrObjectClosed );
1197 if (recordset->index < 0) return MAKE_ADO_HRESULT( adErrNoCurrentRecord );
1199 V_VT(bookmark) = VT_I4;
1200 V_I4(bookmark) = recordset->index;
1201 return S_OK;
1204 static HRESULT WINAPI recordset_put_Bookmark( _Recordset *iface, VARIANT bookmark )
1206 struct recordset *recordset = impl_from_Recordset( iface );
1207 TRACE( "%p, %s\n", iface, debugstr_variant(&bookmark) );
1209 if (recordset->state == adStateClosed) return MAKE_ADO_HRESULT( adErrObjectClosed );
1211 if (V_VT(&bookmark) != VT_I4) return MAKE_ADO_HRESULT( adErrInvalidArgument );
1213 recordset->index = V_I4(&bookmark);
1214 return S_OK;
1217 static HRESULT WINAPI recordset_get_CacheSize( _Recordset *iface, LONG *size )
1219 FIXME( "%p, %p\n", iface, size );
1220 return E_NOTIMPL;
1223 static HRESULT WINAPI recordset_put_CacheSize( _Recordset *iface, LONG size )
1225 FIXME( "%p, %d\n", iface, size );
1226 return E_NOTIMPL;
1229 static HRESULT WINAPI recordset_get_CursorType( _Recordset *iface, CursorTypeEnum *cursor_type )
1231 struct recordset *recordset = impl_from_Recordset( iface );
1233 TRACE( "%p, %p\n", iface, cursor_type );
1235 *cursor_type = recordset->cursor_type;
1236 return S_OK;
1239 static HRESULT WINAPI recordset_put_CursorType( _Recordset *iface, CursorTypeEnum cursor_type )
1241 struct recordset *recordset = impl_from_Recordset( iface );
1243 TRACE( "%p, %d\n", iface, cursor_type );
1245 recordset->cursor_type = cursor_type;
1246 return S_OK;
1249 static HRESULT WINAPI recordset_get_EOF( _Recordset *iface, VARIANT_BOOL *eof )
1251 struct recordset *recordset = impl_from_Recordset( iface );
1253 TRACE( "%p, %p\n", recordset, eof );
1255 *eof = (!recordset->count || recordset->index >= recordset->count) ? VARIANT_TRUE : VARIANT_FALSE;
1256 return S_OK;
1259 static HRESULT WINAPI recordset_get_Fields( _Recordset *iface, Fields **obj )
1261 struct recordset *recordset = impl_from_Recordset( iface );
1262 HRESULT hr;
1264 TRACE( "%p, %p\n", recordset, obj );
1266 if (recordset->fields)
1268 /* yes, this adds a reference to the recordset instead of the fields object */
1269 _Recordset_AddRef( &recordset->Recordset_iface );
1270 recordset->fields->recordset = recordset;
1271 *obj = &recordset->fields->Fields_iface;
1272 return S_OK;
1275 if ((hr = fields_create( recordset, &recordset->fields )) != S_OK) return hr;
1277 *obj = &recordset->fields->Fields_iface;
1278 return S_OK;
1281 static HRESULT WINAPI recordset_get_LockType( _Recordset *iface, LockTypeEnum *lock_type )
1283 FIXME( "%p, %p\n", iface, lock_type );
1284 return E_NOTIMPL;
1287 static HRESULT WINAPI recordset_put_LockType( _Recordset *iface, LockTypeEnum lock_type )
1289 FIXME( "%p, %d\n", iface, lock_type );
1290 return E_NOTIMPL;
1293 static HRESULT WINAPI recordset_get_MaxRecords( _Recordset *iface, LONG *max_records )
1295 FIXME( "%p, %p\n", iface, max_records );
1296 return E_NOTIMPL;
1299 static HRESULT WINAPI recordset_put_MaxRecords( _Recordset *iface, LONG max_records )
1301 FIXME( "%p, %d\n", iface, max_records );
1302 return E_NOTIMPL;
1305 static HRESULT WINAPI recordset_get_RecordCount( _Recordset *iface, LONG *count )
1307 struct recordset *recordset = impl_from_Recordset( iface );
1309 TRACE( "%p, %p\n", recordset, count );
1311 *count = recordset->count;
1312 return S_OK;
1315 static HRESULT WINAPI recordset_putref_Source( _Recordset *iface, IDispatch *source )
1317 FIXME( "%p, %p\n", iface, source );
1318 return E_NOTIMPL;
1321 static HRESULT WINAPI recordset_put_Source( _Recordset *iface, BSTR source )
1323 FIXME( "%p, %s\n", iface, debugstr_w(source) );
1324 return E_NOTIMPL;
1327 static HRESULT WINAPI recordset_get_Source( _Recordset *iface, VARIANT *source )
1329 FIXME( "%p, %p\n", iface, source );
1330 return E_NOTIMPL;
1333 static BOOL resize_recordset( struct recordset *recordset, ULONG row_count )
1335 ULONG row_size = get_column_count( recordset ) * sizeof(*recordset->data);
1337 if (row_count > recordset->allocated)
1339 VARIANT *tmp;
1340 ULONG count = max( row_count, recordset->allocated * 2 );
1341 if (!(tmp = heap_realloc_zero( recordset->data, count * row_size ))) return FALSE;
1342 recordset->data = tmp;
1343 recordset->allocated = count;
1346 recordset->count = row_count;
1347 return TRUE;
1350 static HRESULT WINAPI recordset_AddNew( _Recordset *iface, VARIANT field_list, VARIANT values )
1352 struct recordset *recordset = impl_from_Recordset( iface );
1354 TRACE( "%p, %s, %s\n", recordset, debugstr_variant(&field_list), debugstr_variant(&values) );
1355 FIXME( "ignoring field list and values\n" );
1357 if (recordset->state == adStateClosed) return MAKE_ADO_HRESULT( adErrObjectClosed );
1359 if (!resize_recordset( recordset, recordset->count + 1 )) return E_OUTOFMEMORY;
1360 recordset->index++;
1361 return S_OK;
1364 static HRESULT WINAPI recordset_CancelUpdate( _Recordset *iface )
1366 FIXME( "%p\n", iface );
1367 return E_NOTIMPL;
1370 static HRESULT WINAPI recordset_Close( _Recordset *iface )
1372 struct recordset *recordset = impl_from_Recordset( iface );
1374 TRACE( "%p\n", recordset );
1376 if (recordset->state == adStateClosed) return MAKE_ADO_HRESULT( adErrObjectClosed );
1378 close_recordset( recordset );
1379 recordset->state = adStateClosed;
1380 return S_OK;
1383 static HRESULT WINAPI recordset_Delete( _Recordset *iface, AffectEnum affect_records )
1385 FIXME( "%p, %u\n", iface, affect_records );
1386 return E_NOTIMPL;
1389 static HRESULT WINAPI recordset_GetRows( _Recordset *iface, LONG rows, VARIANT start, VARIANT fields, VARIANT *var )
1391 FIXME( "%p, %d, %s, %s, %p\n", iface, rows, debugstr_variant(&start), debugstr_variant(&fields), var );
1392 return E_NOTIMPL;
1395 static HRESULT WINAPI recordset_Move( _Recordset *iface, LONG num_records, VARIANT start )
1397 FIXME( "%p, %d, %s\n", iface, num_records, debugstr_variant(&start) );
1398 return E_NOTIMPL;
1401 static HRESULT WINAPI recordset_MoveNext( _Recordset *iface )
1403 struct recordset *recordset = impl_from_Recordset( iface );
1405 TRACE( "%p\n", recordset );
1407 if (recordset->index < recordset->count) recordset->index++;
1408 return S_OK;
1411 static HRESULT WINAPI recordset_MovePrevious( _Recordset *iface )
1413 struct recordset *recordset = impl_from_Recordset( iface );
1415 TRACE( "%p\n", recordset );
1417 if (recordset->index >= 0) recordset->index--;
1418 return S_OK;
1421 static HRESULT WINAPI recordset_MoveFirst( _Recordset *iface )
1423 struct recordset *recordset = impl_from_Recordset( iface );
1425 TRACE( "%p\n", recordset );
1427 recordset->index = 0;
1428 return S_OK;
1431 static HRESULT WINAPI recordset_MoveLast( _Recordset *iface )
1433 struct recordset *recordset = impl_from_Recordset( iface );
1435 TRACE( "%p\n", recordset );
1437 recordset->index = (recordset->count > 0) ? recordset->count - 1 : 0;
1438 return S_OK;
1441 static HRESULT create_command_text(IUnknown *session, BSTR command, ICommandText **cmd_text)
1443 HRESULT hr;
1444 IOpenRowset *openrowset;
1445 ICommandText *command_text;
1446 ICommand *cmd;
1447 IDBCreateCommand *create_command;
1449 hr = IUnknown_QueryInterface(session, &IID_IOpenRowset, (void**)&openrowset);
1450 if (FAILED(hr))
1451 return hr;
1453 hr = IOpenRowset_QueryInterface(openrowset, &IID_IDBCreateCommand, (void**)&create_command);
1454 IOpenRowset_Release(openrowset);
1455 if (FAILED(hr))
1456 return hr;
1458 hr = IDBCreateCommand_CreateCommand(create_command, NULL, &IID_IUnknown, (IUnknown **)&cmd);
1459 IDBCreateCommand_Release(create_command);
1460 if (FAILED(hr))
1461 return hr;
1463 hr = ICommand_QueryInterface(cmd, &IID_ICommandText, (void**)&command_text);
1464 ICommand_Release(cmd);
1465 if (FAILED(hr))
1467 FIXME("Currently only ICommandText interface is support\n");
1468 return hr;
1471 hr = ICommandText_SetCommandText(command_text, &DBGUID_DEFAULT, command);
1472 if (FAILED(hr))
1474 ICommandText_Release(command_text);
1475 return hr;
1478 *cmd_text = command_text;
1480 return S_OK;
1483 static HRESULT WINAPI recordset_Open( _Recordset *iface, VARIANT source, VARIANT active_connection,
1484 CursorTypeEnum cursor_type, LockTypeEnum lock_type, LONG options )
1486 struct recordset *recordset = impl_from_Recordset( iface );
1487 ADOConnectionConstruction15 *construct;
1488 IUnknown *session;
1489 ICommandText *command_text;
1490 DBROWCOUNT affected;
1491 IUnknown *rowset;
1492 HRESULT hr;
1494 FIXME( "%p, %s, %s, %d, %d, %d Semi-stub\n", recordset, debugstr_variant(&source), debugstr_variant(&active_connection),
1495 cursor_type, lock_type, options );
1497 if (recordset->state == adStateOpen) return MAKE_ADO_HRESULT( adErrObjectOpen );
1499 if (recordset->fields)
1501 recordset->state = adStateOpen;
1502 return S_OK;
1505 if (V_VT(&active_connection) != VT_DISPATCH)
1507 FIXME("Unsupported Active connection type %d\n", V_VT(&active_connection));
1508 return MAKE_ADO_HRESULT( adErrInvalidConnection );
1511 hr = IDispatch_QueryInterface(V_DISPATCH(&active_connection), &IID_ADOConnectionConstruction15, (void**)&construct);
1512 if (FAILED(hr))
1513 return E_FAIL;
1515 hr = ADOConnectionConstruction15_get_Session(construct, &session);
1516 ADOConnectionConstruction15_Release(construct);
1517 if (FAILED(hr))
1518 return E_FAIL;
1520 if (V_VT(&source) != VT_BSTR)
1522 FIXME("Unsupported source type!\n");
1523 IUnknown_Release(session);
1524 return E_FAIL;
1527 hr = create_command_text(session, V_BSTR(&source), &command_text);
1528 IUnknown_Release(session);
1529 if (FAILED(hr))
1530 return hr;
1532 hr = ICommandText_Execute(command_text, NULL, &IID_IUnknown, NULL, &affected, &rowset);
1533 ICommandText_Release(command_text);
1534 if (FAILED(hr) || !rowset)
1535 return hr;
1537 ADORecordsetConstruction_put_Rowset(&recordset->ADORecordsetConstruction_iface, rowset);
1538 recordset->cursor_type = cursor_type;
1539 recordset->state = adStateOpen;
1541 IUnknown_Release(rowset);
1543 return hr;
1546 static HRESULT WINAPI recordset_Requery( _Recordset *iface, LONG options )
1548 FIXME( "%p, %d\n", iface, options );
1549 return E_NOTIMPL;
1552 static HRESULT WINAPI recordset__xResync( _Recordset *iface, AffectEnum affect_records )
1554 FIXME( "%p, %u\n", iface, affect_records );
1555 return E_NOTIMPL;
1558 static HRESULT WINAPI recordset_Update( _Recordset *iface, VARIANT fields, VARIANT values )
1560 FIXME( "%p, %s, %s\n", iface, debugstr_variant(&fields), debugstr_variant(&values) );
1561 return E_NOTIMPL;
1564 static HRESULT WINAPI recordset_get_AbsolutePage( _Recordset *iface, PositionEnum_Param *pos )
1566 FIXME( "%p, %p\n", iface, pos );
1567 return E_NOTIMPL;
1570 static HRESULT WINAPI recordset_put_AbsolutePage( _Recordset *iface, PositionEnum_Param pos )
1572 FIXME( "%p, %d\n", iface, pos );
1573 return E_NOTIMPL;
1576 static HRESULT WINAPI recordset_get_EditMode( _Recordset *iface, EditModeEnum *mode )
1578 FIXME( "%p, %p\n", iface, mode );
1579 return E_NOTIMPL;
1582 static HRESULT WINAPI recordset_get_Filter( _Recordset *iface, VARIANT *criteria )
1584 FIXME( "%p, %p\n", iface, criteria );
1585 return E_NOTIMPL;
1588 static HRESULT WINAPI recordset_put_Filter( _Recordset *iface, VARIANT criteria )
1590 FIXME( "%p, %s\n", iface, debugstr_variant(&criteria) );
1591 return E_NOTIMPL;
1594 static HRESULT WINAPI recordset_get_PageCount( _Recordset *iface, LONG *count )
1596 FIXME( "%p, %p\n", iface, count );
1597 return E_NOTIMPL;
1600 static HRESULT WINAPI recordset_get_PageSize( _Recordset *iface, LONG *size )
1602 FIXME( "%p, %p\n", iface, size );
1603 return E_NOTIMPL;
1606 static HRESULT WINAPI recordset_put_PageSize( _Recordset *iface, LONG size )
1608 FIXME( "%p, %d\n", iface, size );
1609 return E_NOTIMPL;
1612 static HRESULT WINAPI recordset_get_Sort( _Recordset *iface, BSTR *criteria )
1614 FIXME( "%p, %p\n", iface, criteria );
1615 return E_NOTIMPL;
1618 static HRESULT WINAPI recordset_put_Sort( _Recordset *iface, BSTR criteria )
1620 FIXME( "%p, %s\n", iface, debugstr_w(criteria) );
1621 return E_NOTIMPL;
1624 static HRESULT WINAPI recordset_get_Status( _Recordset *iface, LONG *status )
1626 FIXME( "%p, %p\n", iface, status );
1627 return E_NOTIMPL;
1630 static HRESULT WINAPI recordset_get_State( _Recordset *iface, LONG *state )
1632 struct recordset *recordset = impl_from_Recordset( iface );
1634 TRACE( "%p, %p\n", recordset, state );
1636 *state = recordset->state;
1637 return S_OK;
1640 static HRESULT WINAPI recordset__xClone( _Recordset *iface, _Recordset **obj )
1642 FIXME( "%p, %p\n", iface, obj );
1643 return E_NOTIMPL;
1646 static HRESULT WINAPI recordset_UpdateBatch( _Recordset *iface, AffectEnum affect_records )
1648 FIXME( "%p, %u\n", iface, affect_records );
1649 return E_NOTIMPL;
1652 static HRESULT WINAPI recordset_CancelBatch( _Recordset *iface, AffectEnum affect_records )
1654 FIXME( "%p, %u\n", iface, affect_records );
1655 return E_NOTIMPL;
1658 static HRESULT WINAPI recordset_get_CursorLocation( _Recordset *iface, CursorLocationEnum *cursor_loc )
1660 struct recordset *recordset = impl_from_Recordset( iface );
1662 TRACE( "%p, %p\n", iface, cursor_loc );
1664 *cursor_loc = recordset->cursor_location;
1666 return S_OK;
1669 static HRESULT WINAPI recordset_put_CursorLocation( _Recordset *iface, CursorLocationEnum cursor_loc )
1671 struct recordset *recordset = impl_from_Recordset( iface );
1673 TRACE( "%p, %u\n", iface, cursor_loc );
1675 if (recordset->state == adStateOpen) return MAKE_ADO_HRESULT( adErrObjectOpen );
1677 recordset->cursor_location = cursor_loc;
1679 return S_OK;
1682 static HRESULT WINAPI recordset_NextRecordset( _Recordset *iface, VARIANT *records_affected, _Recordset **record_set )
1684 FIXME( "%p, %p, %p\n", iface, records_affected, record_set );
1685 return E_NOTIMPL;
1688 static HRESULT WINAPI recordset_Supports( _Recordset *iface, CursorOptionEnum cursor_options, VARIANT_BOOL *ret )
1690 FIXME( "%p, %08x, %p\n", iface, cursor_options, ret );
1691 return E_NOTIMPL;
1694 static HRESULT WINAPI recordset_get_Collect( _Recordset *iface, VARIANT index, VARIANT *var )
1696 FIXME( "%p, %s, %p\n", iface, debugstr_variant(&index), var );
1697 return E_NOTIMPL;
1700 static HRESULT WINAPI recordset_put_Collect( _Recordset *iface, VARIANT index, VARIANT var )
1702 FIXME( "%p, %s, %s\n", iface, debugstr_variant(&index), debugstr_variant(&var) );
1703 return E_NOTIMPL;
1706 static HRESULT WINAPI recordset_get_MarshalOptions( _Recordset *iface, MarshalOptionsEnum *options )
1708 FIXME( "%p, %p\n", iface, options );
1709 return E_NOTIMPL;
1712 static HRESULT WINAPI recordset_put_MarshalOptions( _Recordset *iface, MarshalOptionsEnum options )
1714 FIXME( "%p, %u\n", iface, options );
1715 return E_NOTIMPL;
1718 static HRESULT WINAPI recordset_Find( _Recordset *iface, BSTR criteria, LONG skip_records,
1719 SearchDirectionEnum search_direction, VARIANT start )
1721 FIXME( "%p, %s, %d, %d, %s\n", iface, debugstr_w(criteria), skip_records, search_direction,
1722 debugstr_variant(&start) );
1723 return E_NOTIMPL;
1726 static HRESULT WINAPI recordset_Cancel( _Recordset *iface )
1728 FIXME( "%p\n", iface );
1729 return E_NOTIMPL;
1732 static HRESULT WINAPI recordset_get_DataSource( _Recordset *iface, IUnknown **data_source )
1734 FIXME( "%p, %p\n", iface, data_source );
1735 return E_NOTIMPL;
1738 static HRESULT WINAPI recordset_putref_DataSource( _Recordset *iface, IUnknown *data_source )
1740 FIXME( "%p, %p\n", iface, data_source );
1741 return E_NOTIMPL;
1744 static HRESULT WINAPI recordset__xSave( _Recordset *iface, BSTR filename, PersistFormatEnum persist_format )
1746 FIXME( "%p, %s, %u\n", iface, debugstr_w(filename), persist_format );
1747 return E_NOTIMPL;
1750 static HRESULT WINAPI recordset_get_ActiveCommand( _Recordset *iface, IDispatch **cmd )
1752 FIXME( "%p, %p\n", iface, cmd );
1753 return E_NOTIMPL;
1756 static HRESULT WINAPI recordset_put_StayInSync( _Recordset *iface, VARIANT_BOOL stay_in_sync )
1758 FIXME( "%p, %d\n", iface, stay_in_sync );
1759 return E_NOTIMPL;
1762 static HRESULT WINAPI recordset_get_StayInSync( _Recordset *iface, VARIANT_BOOL *stay_in_sync )
1764 FIXME( "%p, %p\n", iface, stay_in_sync );
1765 return E_NOTIMPL;
1768 static HRESULT WINAPI recordset_GetString( _Recordset *iface, StringFormatEnum string_format, LONG num_rows,
1769 BSTR column_delimiter, BSTR row_delimiter, BSTR null_expr,
1770 BSTR *ret_string )
1772 FIXME( "%p, %u, %d, %s, %s, %s, %p\n", iface, string_format, num_rows, debugstr_w(column_delimiter),
1773 debugstr_w(row_delimiter), debugstr_w(null_expr), ret_string );
1774 return E_NOTIMPL;
1777 static HRESULT WINAPI recordset_get_DataMember( _Recordset *iface, BSTR *data_member )
1779 FIXME( "%p, %p\n", iface, data_member );
1780 return E_NOTIMPL;
1783 static HRESULT WINAPI recordset_put_DataMember( _Recordset *iface, BSTR data_member )
1785 FIXME( "%p, %s\n", iface, debugstr_w(data_member) );
1786 return E_NOTIMPL;
1789 static HRESULT WINAPI recordset_CompareBookmarks( _Recordset *iface, VARIANT bookmark1, VARIANT bookmark2, CompareEnum *compare )
1791 FIXME( "%p, %s, %s, %p\n", iface, debugstr_variant(&bookmark1), debugstr_variant(&bookmark2), compare );
1792 return E_NOTIMPL;
1795 static HRESULT WINAPI recordset_Clone( _Recordset *iface, LockTypeEnum lock_type, _Recordset **obj )
1797 FIXME( "%p, %d, %p\n", iface, lock_type, obj );
1798 return E_NOTIMPL;
1801 static HRESULT WINAPI recordset_Resync( _Recordset *iface, AffectEnum affect_records, ResyncEnum resync_values )
1803 FIXME( "%p, %u, %u\n", iface, affect_records, resync_values );
1804 return E_NOTIMPL;
1807 static HRESULT WINAPI recordset_Seek( _Recordset *iface, VARIANT key_values, SeekEnum seek_option )
1809 FIXME( "%p, %s, %u\n", iface, debugstr_variant(&key_values), seek_option );
1810 return E_NOTIMPL;
1813 static HRESULT WINAPI recordset_put_Index( _Recordset *iface, BSTR index )
1815 FIXME( "%p, %s\n", iface, debugstr_w(index) );
1816 return E_NOTIMPL;
1819 static HRESULT WINAPI recordset_get_Index( _Recordset *iface, BSTR *index )
1821 FIXME( "%p, %p\n", iface, index );
1822 return E_NOTIMPL;
1825 static HRESULT WINAPI recordset_Save( _Recordset *iface, VARIANT destination, PersistFormatEnum persist_format )
1827 FIXME( "%p, %s, %u\n", iface, debugstr_variant(&destination), persist_format );
1828 return E_NOTIMPL;
1831 static const struct _RecordsetVtbl recordset_vtbl =
1833 recordset_QueryInterface,
1834 recordset_AddRef,
1835 recordset_Release,
1836 recordset_GetTypeInfoCount,
1837 recordset_GetTypeInfo,
1838 recordset_GetIDsOfNames,
1839 recordset_Invoke,
1840 recordset_get_Properties,
1841 recordset_get_AbsolutePosition,
1842 recordset_put_AbsolutePosition,
1843 recordset_putref_ActiveConnection,
1844 recordset_put_ActiveConnection,
1845 recordset_get_ActiveConnection,
1846 recordset_get_BOF,
1847 recordset_get_Bookmark,
1848 recordset_put_Bookmark,
1849 recordset_get_CacheSize,
1850 recordset_put_CacheSize,
1851 recordset_get_CursorType,
1852 recordset_put_CursorType,
1853 recordset_get_EOF,
1854 recordset_get_Fields,
1855 recordset_get_LockType,
1856 recordset_put_LockType,
1857 recordset_get_MaxRecords,
1858 recordset_put_MaxRecords,
1859 recordset_get_RecordCount,
1860 recordset_putref_Source,
1861 recordset_put_Source,
1862 recordset_get_Source,
1863 recordset_AddNew,
1864 recordset_CancelUpdate,
1865 recordset_Close,
1866 recordset_Delete,
1867 recordset_GetRows,
1868 recordset_Move,
1869 recordset_MoveNext,
1870 recordset_MovePrevious,
1871 recordset_MoveFirst,
1872 recordset_MoveLast,
1873 recordset_Open,
1874 recordset_Requery,
1875 recordset__xResync,
1876 recordset_Update,
1877 recordset_get_AbsolutePage,
1878 recordset_put_AbsolutePage,
1879 recordset_get_EditMode,
1880 recordset_get_Filter,
1881 recordset_put_Filter,
1882 recordset_get_PageCount,
1883 recordset_get_PageSize,
1884 recordset_put_PageSize,
1885 recordset_get_Sort,
1886 recordset_put_Sort,
1887 recordset_get_Status,
1888 recordset_get_State,
1889 recordset__xClone,
1890 recordset_UpdateBatch,
1891 recordset_CancelBatch,
1892 recordset_get_CursorLocation,
1893 recordset_put_CursorLocation,
1894 recordset_NextRecordset,
1895 recordset_Supports,
1896 recordset_get_Collect,
1897 recordset_put_Collect,
1898 recordset_get_MarshalOptions,
1899 recordset_put_MarshalOptions,
1900 recordset_Find,
1901 recordset_Cancel,
1902 recordset_get_DataSource,
1903 recordset_putref_DataSource,
1904 recordset__xSave,
1905 recordset_get_ActiveCommand,
1906 recordset_put_StayInSync,
1907 recordset_get_StayInSync,
1908 recordset_GetString,
1909 recordset_get_DataMember,
1910 recordset_put_DataMember,
1911 recordset_CompareBookmarks,
1912 recordset_Clone,
1913 recordset_Resync,
1914 recordset_Seek,
1915 recordset_put_Index,
1916 recordset_get_Index,
1917 recordset_Save
1920 static inline struct recordset *recordset_from_ISupportErrorInfo( ISupportErrorInfo *iface )
1922 return CONTAINING_RECORD( iface, struct recordset, ISupportErrorInfo_iface );
1925 static HRESULT WINAPI recordset_supporterrorinfo_QueryInterface( ISupportErrorInfo *iface, REFIID riid, void **obj )
1927 struct recordset *recordset = recordset_from_ISupportErrorInfo( iface );
1928 return _Recordset_QueryInterface( &recordset->Recordset_iface, riid, obj );
1931 static ULONG WINAPI recordset_supporterrorinfo_AddRef( ISupportErrorInfo *iface )
1933 struct recordset *recordset = recordset_from_ISupportErrorInfo( iface );
1934 return _Recordset_AddRef( &recordset->Recordset_iface );
1937 static ULONG WINAPI recordset_supporterrorinfo_Release( ISupportErrorInfo *iface )
1939 struct recordset *recordset = recordset_from_ISupportErrorInfo( iface );
1940 return _Recordset_Release( &recordset->Recordset_iface );
1943 static HRESULT WINAPI recordset_supporterrorinfo_InterfaceSupportsErrorInfo( ISupportErrorInfo *iface, REFIID riid )
1945 struct recordset *recordset = recordset_from_ISupportErrorInfo( iface );
1946 FIXME( "%p, %s\n", recordset, debugstr_guid(riid) );
1947 return S_FALSE;
1950 static const ISupportErrorInfoVtbl recordset_supporterrorinfo_vtbl =
1952 recordset_supporterrorinfo_QueryInterface,
1953 recordset_supporterrorinfo_AddRef,
1954 recordset_supporterrorinfo_Release,
1955 recordset_supporterrorinfo_InterfaceSupportsErrorInfo
1958 static HRESULT WINAPI rsconstruction_QueryInterface(ADORecordsetConstruction *iface,
1959 REFIID riid, void **obj)
1961 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
1962 return _Recordset_QueryInterface( &recordset->Recordset_iface, riid, obj );
1965 static ULONG WINAPI rsconstruction_AddRef(ADORecordsetConstruction *iface)
1967 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
1968 return _Recordset_AddRef( &recordset->Recordset_iface );
1971 static ULONG WINAPI rsconstruction_Release(ADORecordsetConstruction *iface)
1973 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
1974 return _Recordset_Release( &recordset->Recordset_iface );
1977 static HRESULT WINAPI rsconstruction_GetTypeInfoCount(ADORecordsetConstruction *iface, UINT *pctinfo)
1979 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
1980 TRACE( "%p, %p\n", recordset, pctinfo );
1981 *pctinfo = 1;
1982 return S_OK;
1985 static HRESULT WINAPI rsconstruction_GetTypeInfo(ADORecordsetConstruction *iface, UINT iTInfo,
1986 LCID lcid, ITypeInfo **ppTInfo)
1988 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
1989 TRACE( "%p %u %u %p\n", recordset, iTInfo, lcid, ppTInfo );
1990 return get_typeinfo(ADORecordsetConstruction_tid, ppTInfo);
1993 static HRESULT WINAPI rsconstruction_GetIDsOfNames(ADORecordsetConstruction *iface, REFIID riid,
1994 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1996 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
1997 HRESULT hr;
1998 ITypeInfo *typeinfo;
2000 TRACE( "%p %s %p %u %u %p\n", recordset, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId );
2002 hr = get_typeinfo(ADORecordsetConstruction_tid, &typeinfo);
2003 if(SUCCEEDED(hr))
2005 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
2006 ITypeInfo_Release(typeinfo);
2009 return hr;
2012 static HRESULT WINAPI rsconstruction_Invoke(ADORecordsetConstruction *iface, DISPID dispIdMember,
2013 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
2014 EXCEPINFO *pExcepInfo, UINT *puArgErr)
2016 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
2017 HRESULT hr;
2018 ITypeInfo *typeinfo;
2020 TRACE( "%p %d %s %d %d %p %p %p %p\n", recordset, dispIdMember, debugstr_guid(riid),
2021 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr );
2023 hr = get_typeinfo(ADORecordsetConstruction_tid, &typeinfo);
2024 if(SUCCEEDED(hr))
2026 hr = ITypeInfo_Invoke(typeinfo, &recordset->ADORecordsetConstruction_iface, dispIdMember, wFlags,
2027 pDispParams, pVarResult, pExcepInfo, puArgErr);
2028 ITypeInfo_Release(typeinfo);
2031 return hr;
2034 static HRESULT WINAPI rsconstruction_get_Rowset(ADORecordsetConstruction *iface, IUnknown **row_set)
2036 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
2037 HRESULT hr;
2039 TRACE( "%p, %p\n", recordset, row_set );
2041 hr = IRowset_QueryInterface(recordset->row_set, &IID_IUnknown, (void**)row_set);
2042 if ( FAILED(hr) ) return E_FAIL;
2044 return S_OK;
2047 static HRESULT WINAPI rsconstruction_put_Rowset(ADORecordsetConstruction *iface, IUnknown *unk)
2049 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
2050 HRESULT hr;
2051 IRowset *rowset;
2053 TRACE( "%p, %p\n", recordset, unk );
2055 hr = IUnknown_QueryInterface(unk, &IID_IRowset, (void**)&rowset);
2056 if ( FAILED(hr) ) return E_FAIL;
2058 if ( recordset->row_set ) IRowset_Release( recordset->row_set );
2059 recordset->row_set = rowset;
2061 return S_OK;
2064 static HRESULT WINAPI rsconstruction_get_Chapter(ADORecordsetConstruction *iface, LONG *chapter)
2066 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
2067 FIXME( "%p, %p\n", recordset, chapter );
2068 return E_NOTIMPL;
2071 static HRESULT WINAPI rsconstruction_put_Chapter(ADORecordsetConstruction *iface, LONG chapter)
2073 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
2074 FIXME( "%p, %d\n", recordset, chapter );
2075 return E_NOTIMPL;
2078 static HRESULT WINAPI rsconstruction_get_RowPosition(ADORecordsetConstruction *iface, IUnknown **row_pos)
2080 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
2081 FIXME( "%p, %p\n", recordset, row_pos );
2082 return E_NOTIMPL;
2085 static HRESULT WINAPI rsconstruction_put_RowPosition(ADORecordsetConstruction *iface, IUnknown *row_pos)
2087 struct recordset *recordset = impl_from_ADORecordsetConstruction( iface );
2088 FIXME( "%p, %p\n", recordset, row_pos );
2089 return E_NOTIMPL;
2092 static const ADORecordsetConstructionVtbl rsconstruction_vtbl =
2094 rsconstruction_QueryInterface,
2095 rsconstruction_AddRef,
2096 rsconstruction_Release,
2097 rsconstruction_GetTypeInfoCount,
2098 rsconstruction_GetTypeInfo,
2099 rsconstruction_GetIDsOfNames,
2100 rsconstruction_Invoke,
2101 rsconstruction_get_Rowset,
2102 rsconstruction_put_Rowset,
2103 rsconstruction_get_Chapter,
2104 rsconstruction_put_Chapter,
2105 rsconstruction_get_RowPosition,
2106 rsconstruction_put_RowPosition
2109 HRESULT Recordset_create( void **obj )
2111 struct recordset *recordset;
2113 if (!(recordset = heap_alloc_zero( sizeof(*recordset) ))) return E_OUTOFMEMORY;
2114 recordset->Recordset_iface.lpVtbl = &recordset_vtbl;
2115 recordset->ISupportErrorInfo_iface.lpVtbl = &recordset_supporterrorinfo_vtbl;
2116 recordset->ADORecordsetConstruction_iface.lpVtbl = &rsconstruction_vtbl;
2117 recordset->refs = 1;
2118 recordset->index = -1;
2119 recordset->cursor_location = adUseServer;
2120 recordset->cursor_type = adOpenForwardOnly;
2121 recordset->row_set = NULL;
2123 *obj = &recordset->Recordset_iface;
2124 TRACE( "returning iface %p\n", *obj );
2125 return S_OK;