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
25 #include "msado15_backcompat.h"
29 #include "wine/debug.h"
31 #include "msado15_private.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(msado15
);
38 _Recordset Recordset_iface
;
39 ADORecordsetConstruction ADORecordsetConstruction_iface
;
40 ISupportErrorInfo ISupportErrorInfo_iface
;
42 VARIANT active_connection
;
44 struct fields
*fields
;
49 CursorLocationEnum cursor_location
;
50 CursorTypeEnum cursor_type
;
52 EditModeEnum editmode
;
56 HACCESSOR
*haccessors
;
62 ISupportErrorInfo ISupportErrorInfo_iface
;
67 struct recordset
*recordset
;
73 ISupportErrorInfo ISupportErrorInfo_iface
;
74 Properties Properties_iface
;
81 struct recordset
*recordset
;
83 /* Field Properties */
87 static inline struct field
*impl_from_Field( Field
*iface
)
89 return CONTAINING_RECORD( iface
, struct field
, Field_iface
);
92 static inline struct field
*impl_from_Properties( Properties
*iface
)
94 return CONTAINING_RECORD( iface
, struct field
, Properties_iface
);
97 static ULONG WINAPI
field_AddRef( Field
*iface
)
99 struct field
*field
= impl_from_Field( iface
);
100 LONG refs
= InterlockedIncrement( &field
->refs
);
101 TRACE( "%p new refcount %ld\n", field
, refs
);
105 static ULONG WINAPI
field_Release( Field
*iface
)
107 struct field
*field
= impl_from_Field( iface
);
108 LONG refs
= InterlockedDecrement( &field
->refs
);
109 TRACE( "%p new refcount %ld\n", field
, refs
);
112 TRACE( "destroying %p\n", field
);
119 static HRESULT WINAPI
field_QueryInterface( Field
*iface
, REFIID riid
, void **obj
)
121 struct field
*field
= impl_from_Field( iface
);
122 TRACE( "%p, %s, %p\n", iface
, debugstr_guid(riid
), obj
);
124 if (IsEqualGUID( riid
, &IID_Field
) || IsEqualGUID( riid
, &IID_IDispatch
) ||
125 IsEqualGUID( riid
, &IID_IUnknown
))
129 else if (IsEqualGUID( riid
, &IID_ISupportErrorInfo
))
131 *obj
= &field
->ISupportErrorInfo_iface
;
135 FIXME( "interface %s not implemented\n", debugstr_guid(riid
) );
136 return E_NOINTERFACE
;
138 field_AddRef( iface
);
142 static HRESULT WINAPI
field_GetTypeInfoCount( Field
*iface
, UINT
*count
)
144 struct field
*field
= impl_from_Field( iface
);
145 TRACE( "%p, %p\n", field
, count
);
150 static HRESULT WINAPI
field_GetTypeInfo( Field
*iface
, UINT index
, LCID lcid
, ITypeInfo
**info
)
152 struct field
*field
= impl_from_Field( iface
);
153 TRACE( "%p, %u, %lu, %p\n", field
, index
, lcid
, info
);
154 return get_typeinfo(Field_tid
, info
);
157 static HRESULT WINAPI
field_GetIDsOfNames( Field
*iface
, REFIID riid
, LPOLESTR
*names
, UINT count
,
158 LCID lcid
, DISPID
*dispid
)
160 struct field
*field
= impl_from_Field( iface
);
164 TRACE( "%p, %s, %p, %u, %lu, %p\n", field
, debugstr_guid(riid
), names
, count
, lcid
, dispid
);
166 hr
= get_typeinfo(Field_tid
, &typeinfo
);
169 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, names
, count
, dispid
);
170 ITypeInfo_Release(typeinfo
);
176 static HRESULT WINAPI
field_Invoke( Field
*iface
, DISPID member
, REFIID riid
, LCID lcid
, WORD flags
,
177 DISPPARAMS
*params
, VARIANT
*result
, EXCEPINFO
*excep_info
, UINT
*arg_err
)
179 struct field
*field
= impl_from_Field( iface
);
183 TRACE( "%p, %ld, %s, %ld, %d, %p, %p, %p, %p\n", field
, member
, debugstr_guid(riid
), lcid
, flags
, params
,
184 result
, excep_info
, arg_err
);
186 hr
= get_typeinfo(Field_tid
, &typeinfo
);
189 hr
= ITypeInfo_Invoke(typeinfo
, &field
->Field_iface
, member
, flags
, params
,
190 result
, excep_info
, arg_err
);
191 ITypeInfo_Release(typeinfo
);
197 static HRESULT WINAPI
field_get_Properties( Field
*iface
, Properties
**obj
)
199 struct field
*field
= impl_from_Field( iface
);
200 TRACE( "%p, %p\n", iface
, obj
);
202 *obj
= &field
->Properties_iface
;
203 Properties_AddRef(&field
->Properties_iface
);
207 static HRESULT WINAPI
field_get_ActualSize( Field
*iface
, ADO_LONGPTR
*size
)
209 struct field
*field
= impl_from_Field( iface
);
210 FIXME( "%p, %p\n", field
, size
);
215 static HRESULT WINAPI
field_get_Attributes( Field
*iface
, LONG
*attrs
)
217 struct field
*field
= impl_from_Field( iface
);
219 TRACE( "%p, %p\n", field
, attrs
);
221 *attrs
= field
->attrs
;
225 static HRESULT WINAPI
field_get_DefinedSize( Field
*iface
, ADO_LONGPTR
*size
)
227 struct field
*field
= impl_from_Field( iface
);
229 TRACE( "%p, %p\n", field
, size
);
231 *size
= field
->defined_size
;
235 static HRESULT WINAPI
field_get_Name( Field
*iface
, BSTR
*str
)
237 struct field
*field
= impl_from_Field( iface
);
240 TRACE( "%p, %p\n", field
, str
);
242 if (!(name
= SysAllocString( field
->name
))) return E_OUTOFMEMORY
;
247 static HRESULT WINAPI
field_get_Type( Field
*iface
, DataTypeEnum
*type
)
249 struct field
*field
= impl_from_Field( iface
);
251 TRACE( "%p, %p\n", field
, type
);
257 static LONG
get_column_count( struct recordset
*recordset
)
259 return recordset
->fields
->count
;
262 static HRESULT WINAPI
field_get_Value( Field
*iface
, VARIANT
*val
)
264 struct field
*field
= impl_from_Field( iface
);
265 ULONG row
= field
->recordset
->index
, col
= field
->index
, col_count
;
269 TRACE( "%p, %p\n", field
, val
);
271 if (field
->recordset
->state
== adStateClosed
) return MAKE_ADO_HRESULT( adErrObjectClosed
);
272 if (field
->recordset
->index
< 0) return MAKE_ADO_HRESULT( adErrNoCurrentRecord
);
274 col_count
= get_column_count( field
->recordset
);
276 VariantInit( ©
);
277 if ((hr
= VariantCopy( ©
, &field
->recordset
->data
[row
* col_count
+ col
] )) != S_OK
) return hr
;
283 static HRESULT WINAPI
field_put_Value( Field
*iface
, VARIANT val
)
285 struct field
*field
= impl_from_Field( iface
);
286 ULONG row
= field
->recordset
->index
, col
= field
->index
, col_count
;
290 TRACE( "%p, %s\n", field
, debugstr_variant(&val
) );
292 if (field
->recordset
->state
== adStateClosed
) return MAKE_ADO_HRESULT( adErrObjectClosed
);
293 if (field
->recordset
->index
< 0) return MAKE_ADO_HRESULT( adErrNoCurrentRecord
);
295 col_count
= get_column_count( field
->recordset
);
297 VariantInit( ©
);
298 if ((hr
= VariantCopy( ©
, &val
)) != S_OK
) return hr
;
300 field
->recordset
->data
[row
* col_count
+ col
] = copy
;
304 static HRESULT WINAPI
field_get_Precision( Field
*iface
, unsigned char *precision
)
306 FIXME( "%p, %p\n", iface
, precision
);
310 static HRESULT WINAPI
field_get_NumericScale( Field
*iface
, unsigned char *scale
)
312 FIXME( "%p, %p\n", iface
, scale
);
316 static HRESULT WINAPI
field_AppendChunk( Field
*iface
, VARIANT data
)
318 FIXME( "%p, %s\n", iface
, debugstr_variant(&data
) );
322 static HRESULT WINAPI
field_GetChunk( Field
*iface
, LONG length
, VARIANT
*var
)
324 FIXME( "%p, %ld, %p\n", iface
, length
, var
);
328 static HRESULT WINAPI
field_get_OriginalValue( Field
*iface
, VARIANT
*val
)
330 FIXME( "%p, %p\n", iface
, val
);
334 static HRESULT WINAPI
field_get_UnderlyingValue( Field
*iface
, VARIANT
*val
)
336 FIXME( "%p, %p\n", iface
, val
);
340 static HRESULT WINAPI
field_get_DataFormat( Field
*iface
, IUnknown
**format
)
342 FIXME( "%p, %p\n", iface
, format
);
346 static HRESULT WINAPI
field_putref_DataFormat( Field
*iface
, IUnknown
*format
)
348 FIXME( "%p, %p\n", iface
, format
);
352 static HRESULT WINAPI
field_put_Precision( Field
*iface
, unsigned char precision
)
354 FIXME( "%p, %c\n", iface
, precision
);
358 static HRESULT WINAPI
field_put_NumericScale( Field
*iface
, unsigned char scale
)
360 FIXME( "%p, %c\n", iface
, scale
);
364 static HRESULT WINAPI
field_put_Type( Field
*iface
, DataTypeEnum type
)
366 struct field
*field
= impl_from_Field( iface
);
368 TRACE( "%p, %u\n", field
, type
);
374 static HRESULT WINAPI
field_put_DefinedSize( Field
*iface
, ADO_LONGPTR size
)
376 struct field
*field
= impl_from_Field( iface
);
378 TRACE( "%p, %Id\n", field
, size
);
380 field
->defined_size
= size
;
384 static HRESULT WINAPI
field_put_Attributes( Field
*iface
, LONG attrs
)
386 struct field
*field
= impl_from_Field( iface
);
388 TRACE( "%p, %ld\n", field
, attrs
);
390 field
->attrs
= attrs
;
394 static HRESULT WINAPI
field_get_Status( Field
*iface
, LONG
*status
)
396 FIXME( "%p, %p\n", iface
, status
);
400 static const struct FieldVtbl field_vtbl
=
402 field_QueryInterface
,
405 field_GetTypeInfoCount
,
409 field_get_Properties
,
410 field_get_ActualSize
,
411 field_get_Attributes
,
412 field_get_DefinedSize
,
418 field_get_NumericScale
,
421 field_get_OriginalValue
,
422 field_get_UnderlyingValue
,
423 field_get_DataFormat
,
424 field_putref_DataFormat
,
426 field_put_NumericScale
,
428 field_put_DefinedSize
,
429 field_put_Attributes
,
433 static inline struct field
*field_from_ISupportErrorInfo( ISupportErrorInfo
*iface
)
435 return CONTAINING_RECORD( iface
, struct field
, ISupportErrorInfo_iface
);
438 static HRESULT WINAPI
field_supporterrorinfo_QueryInterface( ISupportErrorInfo
*iface
, REFIID riid
, void **obj
)
440 struct field
*field
= field_from_ISupportErrorInfo( iface
);
441 return Field_QueryInterface( &field
->Field_iface
, riid
, obj
);
444 static ULONG WINAPI
field_supporterrorinfo_AddRef( ISupportErrorInfo
*iface
)
446 struct field
*field
= field_from_ISupportErrorInfo( iface
);
447 return Field_AddRef( &field
->Field_iface
);
450 static ULONG WINAPI
field_supporterrorinfo_Release( ISupportErrorInfo
*iface
)
452 struct field
*field
= field_from_ISupportErrorInfo( iface
);
453 return Field_Release( &field
->Field_iface
);
456 static HRESULT WINAPI
field_supporterrorinfo_InterfaceSupportsErrorInfo( ISupportErrorInfo
*iface
, REFIID riid
)
458 struct field
*field
= field_from_ISupportErrorInfo( iface
);
459 FIXME( "%p, %s\n", field
, debugstr_guid(riid
) );
463 static const ISupportErrorInfoVtbl field_supporterrorinfo_vtbl
=
465 field_supporterrorinfo_QueryInterface
,
466 field_supporterrorinfo_AddRef
,
467 field_supporterrorinfo_Release
,
468 field_supporterrorinfo_InterfaceSupportsErrorInfo
471 static HRESULT WINAPI
field_props_QueryInterface(Properties
*iface
, REFIID riid
, void **ppv
)
473 struct field
*field
= impl_from_Properties( iface
);
475 if (IsEqualGUID( riid
, &IID_Properties
) || IsEqualGUID( riid
, &IID_IDispatch
) ||
476 IsEqualGUID( riid
, &IID_IUnknown
))
478 *ppv
= &field
->Properties_iface
;
482 FIXME( "interface %s not implemented\n", debugstr_guid(riid
) );
483 return E_NOINTERFACE
;
485 Field_AddRef(&field
->Field_iface
);
489 static ULONG WINAPI
field_props_AddRef(Properties
*iface
)
491 struct field
*field
= impl_from_Properties( iface
);
492 return Field_AddRef(&field
->Field_iface
);
495 static ULONG WINAPI
field_props_Release(Properties
*iface
)
497 struct field
*field
= impl_from_Properties( iface
);
498 return Field_Release(&field
->Field_iface
);
501 static HRESULT WINAPI
field_props_GetTypeInfoCount(Properties
*iface
, UINT
*count
)
503 struct field
*field
= impl_from_Properties( iface
);
504 TRACE( "%p, %p\n", field
, count
);
509 static HRESULT WINAPI
field_props_GetTypeInfo(Properties
*iface
, UINT index
, LCID lcid
, ITypeInfo
**info
)
511 struct field
*field
= impl_from_Properties( iface
);
512 TRACE( "%p, %u, %lu, %p\n", field
, index
, lcid
, info
);
513 return get_typeinfo(Properties_tid
, info
);
516 static HRESULT WINAPI
field_props_GetIDsOfNames(Properties
*iface
, REFIID riid
, LPOLESTR
*names
, UINT count
,
517 LCID lcid
, DISPID
*dispid
)
519 struct field
*field
= impl_from_Properties( iface
);
523 TRACE( "%p, %s, %p, %u, %lu, %p\n", field
, debugstr_guid(riid
), names
, count
, lcid
, dispid
);
525 hr
= get_typeinfo(Properties_tid
, &typeinfo
);
528 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, names
, count
, dispid
);
529 ITypeInfo_Release(typeinfo
);
535 static HRESULT WINAPI
field_props_Invoke(Properties
*iface
, DISPID member
, REFIID riid
, LCID lcid
, WORD flags
,
536 DISPPARAMS
*params
, VARIANT
*result
, EXCEPINFO
*excep_info
, UINT
*arg_err
)
538 struct field
*field
= impl_from_Properties( iface
);
542 TRACE( "%p, %ld, %s, %ld, %d, %p, %p, %p, %p\n", field
, member
, debugstr_guid(riid
), lcid
, flags
, params
,
543 result
, excep_info
, arg_err
);
545 hr
= get_typeinfo(Properties_tid
, &typeinfo
);
548 hr
= ITypeInfo_Invoke(typeinfo
, &field
->Field_iface
, member
, flags
, params
,
549 result
, excep_info
, arg_err
);
550 ITypeInfo_Release(typeinfo
);
556 static HRESULT WINAPI
field_props_get_Count(Properties
*iface
, LONG
*count
)
558 struct field
*field
= impl_from_Properties( iface
);
559 FIXME( "%p, %p\n", field
, count
);
564 static HRESULT WINAPI
field_props__NewEnum(Properties
*iface
, IUnknown
**object
)
566 struct field
*field
= impl_from_Properties( iface
);
567 FIXME( "%p, %p\n", field
, object
);
571 static HRESULT WINAPI
field_props_Refresh(Properties
*iface
)
573 struct field
*field
= impl_from_Properties( iface
);
574 FIXME( "%p\n", field
);
579 struct field_property
581 Property Property_iface
;
586 static inline struct field_property
*impl_from_Property( Property
*iface
)
588 return CONTAINING_RECORD( iface
, struct field_property
, Property_iface
);
591 static ULONG WINAPI
field_property_AddRef(Property
*iface
)
593 struct field_property
*property
= impl_from_Property( iface
);
594 LONG refs
= InterlockedIncrement( &property
->refs
);
595 TRACE( "%p new refcount %ld\n", property
, refs
);
599 static ULONG WINAPI
field_property_Release(Property
*iface
)
601 struct field_property
*property
= impl_from_Property( iface
);
602 LONG refs
= InterlockedDecrement( &property
->refs
);
603 TRACE( "%p new refcount %ld\n", property
, refs
);
611 static HRESULT WINAPI
field_property_QueryInterface(Property
*iface
, REFIID riid
, void **obj
)
613 struct field_property
*property
= impl_from_Property( iface
);
614 TRACE( "%p, %s, %p\n", property
, debugstr_guid(riid
), obj
);
616 if (IsEqualGUID( riid
, &IID_Property
)
617 || IsEqualGUID( riid
, &IID_IDispatch
)
618 || IsEqualGUID( riid
, &IID_IUnknown
))
624 FIXME( "interface %s not implemented\n", debugstr_guid(riid
) );
625 return E_NOINTERFACE
;
627 field_property_AddRef( iface
);
631 static HRESULT WINAPI
field_property_GetTypeInfoCount(Property
*iface
, UINT
*count
)
633 struct field_property
*property
= impl_from_Property( iface
);
634 TRACE( "%p, %p\n", property
, count
);
639 static HRESULT WINAPI
field_property_GetTypeInfo(Property
*iface
, UINT index
, LCID lcid
, ITypeInfo
**info
)
641 struct field_property
*property
= impl_from_Property( iface
);
642 TRACE( "%p, %u, %lu, %p\n", property
, index
, lcid
, info
);
643 return get_typeinfo(Property_tid
, info
);
646 static HRESULT WINAPI
field_property_GetIDsOfNames(Property
*iface
, REFIID riid
, LPOLESTR
*names
, UINT count
,
647 LCID lcid
, DISPID
*dispid
)
649 struct field_property
*property
= impl_from_Property( iface
);
653 TRACE( "%p, %s, %p, %u, %lu, %p\n", property
, debugstr_guid(riid
), names
, count
, lcid
, dispid
);
655 hr
= get_typeinfo(Property_tid
, &typeinfo
);
658 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, names
, count
, dispid
);
659 ITypeInfo_Release(typeinfo
);
665 static HRESULT WINAPI
field_property_Invoke(Property
*iface
, DISPID member
, REFIID riid
, LCID lcid
,
666 WORD flags
, DISPPARAMS
*params
, VARIANT
*result
, EXCEPINFO
*excep_info
, UINT
*arg_err
)
668 struct field_property
*property
= impl_from_Property( iface
);
672 TRACE( "%p, %ld, %s, %ld, %d, %p, %p, %p, %p\n", property
, member
, debugstr_guid(riid
), lcid
, flags
, params
,
673 result
, excep_info
, arg_err
);
675 hr
= get_typeinfo(Property_tid
, &typeinfo
);
678 hr
= ITypeInfo_Invoke(typeinfo
, &property
->Property_iface
, member
, flags
, params
,
679 result
, excep_info
, arg_err
);
680 ITypeInfo_Release(typeinfo
);
686 static HRESULT WINAPI
field_property_get_Value(Property
*iface
, VARIANT
*val
)
688 struct field_property
*property
= impl_from_Property( iface
);
689 TRACE("%p, %p\n", property
, val
);
690 VariantCopy(val
, property
->value
);
694 static HRESULT WINAPI
field_property_put_Value(Property
*iface
, VARIANT val
)
696 struct field_property
*property
= impl_from_Property( iface
);
697 TRACE("%p, %s\n", property
, debugstr_variant(&val
));
698 VariantCopy(property
->value
, &val
);
702 static HRESULT WINAPI
field_property_get_Name(Property
*iface
, BSTR
*str
)
708 static HRESULT WINAPI
field_property_get_Type(Property
*iface
, DataTypeEnum
*type
)
714 static HRESULT WINAPI
field_property_get_Attributes(Property
*iface
, LONG
*attributes
)
720 static HRESULT WINAPI
field_property_put_Attributes(Property
*iface
, LONG attributes
)
726 static struct PropertyVtbl field_property_vtbl
=
728 field_property_QueryInterface
,
729 field_property_AddRef
,
730 field_property_Release
,
731 field_property_GetTypeInfoCount
,
732 field_property_GetTypeInfo
,
733 field_property_GetIDsOfNames
,
734 field_property_Invoke
,
735 field_property_get_Value
,
736 field_property_put_Value
,
737 field_property_get_Name
,
738 field_property_get_Type
,
739 field_property_get_Attributes
,
740 field_property_put_Attributes
743 static HRESULT WINAPI
field_props_get_Item(Properties
*iface
, VARIANT index
, Property
**object
)
745 struct field
*field
= impl_from_Properties( iface
);
746 struct field_property
*prop
;
748 TRACE( "%p, %s, %p\n", field
, debugstr_variant(&index
), object
);
750 if (V_VT(&index
) == VT_BSTR
)
752 if(!wcscmp(L
"Optimize", V_BSTR(&index
)))
754 prop
= malloc (sizeof(struct field_property
));
755 prop
->Property_iface
.lpVtbl
= &field_property_vtbl
;
756 prop
->value
= &field
->optimize
;
758 *object
= &prop
->Property_iface
;
763 FIXME("Unsupported property %s\n", debugstr_variant(&index
));
765 return MAKE_ADO_HRESULT(adErrItemNotFound
);
768 static struct PropertiesVtbl field_properties_vtbl
=
770 field_props_QueryInterface
,
773 field_props_GetTypeInfoCount
,
774 field_props_GetTypeInfo
,
775 field_props_GetIDsOfNames
,
777 field_props_get_Count
,
778 field_props__NewEnum
,
783 static HRESULT
Field_create( const WCHAR
*name
, LONG index
, struct recordset
*recordset
, Field
**obj
)
787 if (!(field
= calloc( 1, sizeof(*field
) ))) return E_OUTOFMEMORY
;
788 field
->Field_iface
.lpVtbl
= &field_vtbl
;
789 field
->ISupportErrorInfo_iface
.lpVtbl
= &field_supporterrorinfo_vtbl
;
790 field
->Properties_iface
.lpVtbl
= &field_properties_vtbl
;
792 if (!(field
->name
= wcsdup( name
)))
795 return E_OUTOFMEMORY
;
797 field
->index
= index
;
798 field
->recordset
= recordset
;
800 *obj
= &field
->Field_iface
;
801 TRACE( "returning iface %p\n", *obj
);
805 static inline struct fields
*impl_from_Fields( Fields
*iface
)
807 return CONTAINING_RECORD( iface
, struct fields
, Fields_iface
);
810 static ULONG WINAPI
fields_AddRef( Fields
*iface
)
812 struct fields
*fields
= impl_from_Fields( iface
);
813 LONG refs
= InterlockedIncrement( &fields
->refs
);
814 TRACE( "%p new refcount %ld\n", fields
, refs
);
818 static ULONG WINAPI
fields_Release( Fields
*iface
)
820 struct fields
*fields
= impl_from_Fields( iface
);
821 LONG refs
= InterlockedDecrement( &fields
->refs
);
822 TRACE( "%p new refcount %ld\n", fields
, refs
);
825 if (fields
->recordset
) _Recordset_Release( &fields
->recordset
->Recordset_iface
);
826 fields
->recordset
= NULL
;
827 WARN( "not destroying %p\n", fields
);
828 return InterlockedIncrement( &fields
->refs
);
833 static HRESULT WINAPI
fields_QueryInterface( Fields
*iface
, REFIID riid
, void **obj
)
835 struct fields
*fields
= impl_from_Fields( iface
);
836 TRACE( "%p, %s, %p\n", iface
, debugstr_guid(riid
), obj
);
838 if (IsEqualGUID( riid
, &IID_Fields
) || IsEqualGUID( riid
, &IID_IDispatch
) ||
839 IsEqualGUID( riid
, &IID_IUnknown
))
843 else if (IsEqualGUID( riid
, &IID_ISupportErrorInfo
))
845 *obj
= &fields
->ISupportErrorInfo_iface
;
849 FIXME( "interface %s not implemented\n", debugstr_guid(riid
) );
850 return E_NOINTERFACE
;
852 fields_AddRef( iface
);
856 static HRESULT WINAPI
fields_GetTypeInfoCount( Fields
*iface
, UINT
*count
)
858 struct fields
*fields
= impl_from_Fields( iface
);
859 TRACE( "%p, %p\n", fields
, count
);
864 static HRESULT WINAPI
fields_GetTypeInfo( Fields
*iface
, UINT index
, LCID lcid
, ITypeInfo
**info
)
866 struct fields
*fields
= impl_from_Fields( iface
);
867 TRACE( "%p, %u, %lu, %p\n", fields
, index
, lcid
, info
);
868 return get_typeinfo(Fields_tid
, info
);
871 static HRESULT WINAPI
fields_GetIDsOfNames( Fields
*iface
, REFIID riid
, LPOLESTR
*names
, UINT count
,
872 LCID lcid
, DISPID
*dispid
)
874 struct fields
*fields
= impl_from_Fields( iface
);
878 TRACE( "%p, %s, %p, %u, %lu, %p\n", fields
, debugstr_guid(riid
), names
, count
, lcid
, dispid
);
880 hr
= get_typeinfo(Fields_tid
, &typeinfo
);
883 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, names
, count
, dispid
);
884 ITypeInfo_Release(typeinfo
);
890 static HRESULT WINAPI
fields_Invoke( Fields
*iface
, DISPID member
, REFIID riid
, LCID lcid
, WORD flags
,
891 DISPPARAMS
*params
, VARIANT
*result
, EXCEPINFO
*excep_info
, UINT
*arg_err
)
893 struct fields
*fields
= impl_from_Fields( iface
);
897 TRACE( "%p, %ld, %s, %ld, %d, %p, %p, %p, %p\n", fields
, member
, debugstr_guid(riid
), lcid
, flags
, params
,
898 result
, excep_info
, arg_err
);
900 hr
= get_typeinfo(Fields_tid
, &typeinfo
);
903 hr
= ITypeInfo_Invoke(typeinfo
, &fields
->Fields_iface
, member
, flags
, params
,
904 result
, excep_info
, arg_err
);
905 ITypeInfo_Release(typeinfo
);
911 static HRESULT WINAPI
fields_get_Count( Fields
*iface
, LONG
*count
)
913 struct fields
*fields
= impl_from_Fields( iface
);
915 TRACE( "%p, %p\n", fields
, count
);
917 *count
= fields
->count
;
921 static HRESULT WINAPI
fields__NewEnum( Fields
*iface
, IUnknown
**obj
)
923 FIXME( "%p, %p\n", iface
, obj
);
927 static HRESULT WINAPI
fields_Refresh( Fields
*iface
)
929 FIXME( "%p\n", iface
);
933 static HRESULT
map_index( struct fields
*fields
, VARIANT
*index
, ULONG
*ret
)
937 if (V_VT( index
) != VT_BSTR
)
942 if (VariantChangeType(&idx
, index
, 0, VT_UI4
) == S_OK
)
945 if (i
< fields
->count
)
952 return MAKE_ADO_HRESULT(adErrItemNotFound
);
955 for (i
= 0; i
< fields
->count
; i
++)
961 if ((hr
= Field_get_Name( fields
->field
[i
], &name
)) != S_OK
) return hr
;
962 match
= !wcsicmp( V_BSTR( index
), name
);
963 SysFreeString( name
);
971 return MAKE_ADO_HRESULT(adErrItemNotFound
);
974 static inline WCHAR
*heap_strdupAtoW(const char *str
)
981 len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
982 ret
= malloc(len
*sizeof(WCHAR
));
984 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, len
);
990 static HRESULT WINAPI
fields_get_Item( Fields
*iface
, VARIANT index
, Field
**obj
)
992 struct fields
*fields
= impl_from_Fields( iface
);
996 TRACE( "%p, %s, %p\n", fields
, debugstr_variant(&index
), obj
);
998 if ((hr
= map_index( fields
, &index
, &i
)) != S_OK
) return hr
;
1000 Field_AddRef( fields
->field
[i
] );
1001 *obj
= fields
->field
[i
];
1005 static BOOL
resize_fields( struct fields
*fields
, ULONG count
)
1007 if (count
> fields
->allocated
)
1010 ULONG new_size
= max( count
, fields
->allocated
* 2 );
1011 if (!(tmp
= realloc( fields
->field
, new_size
* sizeof(*tmp
) ))) return FALSE
;
1012 fields
->field
= tmp
;
1013 fields
->allocated
= new_size
;
1016 fields
->count
= count
;
1020 static HRESULT
append_field( struct fields
*fields
, BSTR name
, DataTypeEnum type
, LONG size
, FieldAttributeEnum attr
,
1026 if ((hr
= Field_create( name
, fields
->count
, fields
->recordset
, &field
)) != S_OK
) return hr
;
1027 Field_put_Type( field
, type
);
1028 Field_put_DefinedSize( field
, size
);
1029 if (attr
!= adFldUnspecified
) Field_put_Attributes( field
, attr
);
1030 if (value
) FIXME( "ignoring value %s\n", debugstr_variant(value
) );
1032 if (!(resize_fields( fields
, fields
->count
+ 1 )))
1034 Field_Release( field
);
1035 return E_OUTOFMEMORY
;
1038 fields
->field
[fields
->count
- 1] = field
;
1042 static HRESULT WINAPI
fields__Append( Fields
*iface
, BSTR name
, DataTypeEnum type
, ADO_LONGPTR size
, FieldAttributeEnum attr
)
1044 struct fields
*fields
= impl_from_Fields( iface
);
1046 TRACE( "%p, %s, %u, %Id, %d\n", fields
, debugstr_w(name
), type
, size
, attr
);
1048 return append_field( fields
, name
, type
, size
, attr
, NULL
);
1051 static HRESULT WINAPI
fields_Delete( Fields
*iface
, VARIANT index
)
1053 FIXME( "%p, %s\n", iface
, debugstr_variant(&index
) );
1057 static HRESULT WINAPI
fields_Append( Fields
*iface
, BSTR name
, DataTypeEnum type
, ADO_LONGPTR size
, FieldAttributeEnum attr
,
1060 struct fields
*fields
= impl_from_Fields( iface
);
1062 TRACE( "%p, %s, %u, %Id, %d, %s\n", fields
, debugstr_w(name
), type
, size
, attr
, debugstr_variant(&value
) );
1064 return append_field( fields
, name
, type
, size
, attr
, &value
);
1067 static HRESULT WINAPI
fields_Update( Fields
*iface
)
1069 FIXME( "%p\n", iface
);
1073 static HRESULT WINAPI
fields_Resync( Fields
*iface
, ResyncEnum resync_values
)
1075 FIXME( "%p, %u\n", iface
, resync_values
);
1079 static HRESULT WINAPI
fields_CancelUpdate( Fields
*iface
)
1081 FIXME( "%p\n", iface
);
1085 static const struct FieldsVtbl fields_vtbl
=
1087 fields_QueryInterface
,
1090 fields_GetTypeInfoCount
,
1092 fields_GetIDsOfNames
,
1106 static inline struct fields
*fields_from_ISupportErrorInfo( ISupportErrorInfo
*iface
)
1108 return CONTAINING_RECORD( iface
, struct fields
, ISupportErrorInfo_iface
);
1111 static HRESULT WINAPI
fields_supporterrorinfo_QueryInterface( ISupportErrorInfo
*iface
, REFIID riid
, void **obj
)
1113 struct fields
*fields
= fields_from_ISupportErrorInfo( iface
);
1114 return Fields_QueryInterface( &fields
->Fields_iface
, riid
, obj
);
1117 static ULONG WINAPI
fields_supporterrorinfo_AddRef( ISupportErrorInfo
*iface
)
1119 struct fields
*fields
= fields_from_ISupportErrorInfo( iface
);
1120 return Fields_AddRef( &fields
->Fields_iface
);
1123 static ULONG WINAPI
fields_supporterrorinfo_Release( ISupportErrorInfo
*iface
)
1125 struct fields
*fields
= fields_from_ISupportErrorInfo( iface
);
1126 return Fields_Release( &fields
->Fields_iface
);
1129 static HRESULT WINAPI
fields_supporterrorinfo_InterfaceSupportsErrorInfo( ISupportErrorInfo
*iface
, REFIID riid
)
1131 struct fields
*fields
= fields_from_ISupportErrorInfo( iface
);
1132 FIXME( "%p, %s\n", fields
, debugstr_guid(riid
) );
1136 static const ISupportErrorInfoVtbl fields_supporterrorinfo_vtbl
=
1138 fields_supporterrorinfo_QueryInterface
,
1139 fields_supporterrorinfo_AddRef
,
1140 fields_supporterrorinfo_Release
,
1141 fields_supporterrorinfo_InterfaceSupportsErrorInfo
1144 static void map_rowset_fields(struct recordset
*recordset
, struct fields
*fields
)
1147 IColumnsInfo
*columninfo
;
1148 DBORDINAL columns
, i
;
1149 DBCOLUMNINFO
*colinfo
;
1150 OLECHAR
*stringsbuffer
;
1152 /* Not Finding the interface or GetColumnInfo failing just causes 0 Fields to be returned */
1153 hr
= IRowset_QueryInterface(recordset
->row_set
, &IID_IColumnsInfo
, (void**)&columninfo
);
1157 hr
= IColumnsInfo_GetColumnInfo(columninfo
, &columns
, &colinfo
, &stringsbuffer
);
1160 for (i
=0; i
< columns
; i
++)
1162 TRACE("Adding Column %Iu, pwszName: %s, pTypeInfo %p, iOrdinal %Iu, dwFlags 0x%08lx, "
1163 "ulColumnSize %Iu, wType %d, bPrecision %d, bScale %d\n",
1164 i
, debugstr_w(colinfo
[i
].pwszName
), colinfo
[i
].pTypeInfo
, colinfo
[i
].iOrdinal
,
1165 colinfo
[i
].dwFlags
, colinfo
[i
].ulColumnSize
, colinfo
[i
].wType
,
1166 colinfo
[i
].bPrecision
, colinfo
[i
].bScale
);
1168 hr
= append_field(fields
, colinfo
[i
].pwszName
, colinfo
[i
].wType
, colinfo
[i
].ulColumnSize
,
1169 colinfo
[i
].dwFlags
, NULL
);
1172 ERR("Failed to add Field name - 0x%08lx\n", hr
);
1177 CoTaskMemFree(colinfo
);
1178 CoTaskMemFree(stringsbuffer
);
1181 IColumnsInfo_Release(columninfo
);
1184 static HRESULT
fields_create( struct recordset
*recordset
, struct fields
**ret
)
1186 struct fields
*fields
;
1188 if (!(fields
= calloc( 1, sizeof(*fields
) ))) return E_OUTOFMEMORY
;
1189 fields
->Fields_iface
.lpVtbl
= &fields_vtbl
;
1190 fields
->ISupportErrorInfo_iface
.lpVtbl
= &fields_supporterrorinfo_vtbl
;
1192 fields
->recordset
= recordset
;
1193 _Recordset_AddRef( &fields
->recordset
->Recordset_iface
);
1195 if ( recordset
->row_set
)
1196 map_rowset_fields(recordset
, fields
);
1199 TRACE( "returning %p\n", *ret
);
1203 static inline struct recordset
*impl_from_Recordset( _Recordset
*iface
)
1205 return CONTAINING_RECORD( iface
, struct recordset
, Recordset_iface
);
1208 static inline struct recordset
*impl_from_ADORecordsetConstruction( ADORecordsetConstruction
*iface
)
1210 return CONTAINING_RECORD( iface
, struct recordset
, ADORecordsetConstruction_iface
);
1213 static ULONG WINAPI
recordset_AddRef( _Recordset
*iface
)
1215 struct recordset
*recordset
= impl_from_Recordset( iface
);
1216 LONG refs
= InterlockedIncrement( &recordset
->refs
);
1217 TRACE( "%p new refcount %ld\n", recordset
, refs
);
1221 static void close_recordset( struct recordset
*recordset
)
1223 ULONG row
, col
, col_count
;
1225 IAccessor
*accessor
;
1227 if (recordset
->haccessors
)
1228 IRowset_QueryInterface(recordset
->row_set
, &IID_IAccessor
, (void**)&accessor
);
1230 if ( recordset
->row_set
) IRowset_Release( recordset
->row_set
);
1231 recordset
->row_set
= NULL
;
1233 VariantClear( &recordset
->filter
);
1235 if (!recordset
->fields
) return;
1236 col_count
= get_column_count( recordset
);
1238 free(recordset
->columntypes
);
1240 for (i
= 0; i
< col_count
; i
++)
1242 struct field
*field
= impl_from_Field( recordset
->fields
->field
[i
] );
1243 field
->recordset
= NULL
;
1244 Field_Release(&field
->Field_iface
);
1246 if (recordset
->haccessors
)
1247 IAccessor_ReleaseAccessor(accessor
, recordset
->haccessors
[i
], NULL
);
1250 if (recordset
->haccessors
)
1252 IAccessor_Release(accessor
);
1253 free(recordset
->haccessors
);
1254 recordset
->haccessors
= NULL
;
1256 recordset
->fields
->count
= 0;
1257 Fields_Release( &recordset
->fields
->Fields_iface
);
1258 recordset
->fields
= NULL
;
1260 for (row
= 0; row
< recordset
->count
; row
++)
1261 for (col
= 0; col
< col_count
; col
++) VariantClear( &recordset
->data
[row
* col_count
+ col
] );
1263 recordset
->count
= recordset
->allocated
= recordset
->index
= 0;
1264 free( recordset
->data
);
1265 recordset
->data
= NULL
;
1268 static ULONG WINAPI
recordset_Release( _Recordset
*iface
)
1270 struct recordset
*recordset
= impl_from_Recordset( iface
);
1271 LONG refs
= InterlockedDecrement( &recordset
->refs
);
1272 TRACE( "%p new refcount %ld\n", recordset
, refs
);
1275 TRACE( "destroying %p\n", recordset
);
1276 close_recordset( recordset
);
1282 static HRESULT WINAPI
recordset_QueryInterface( _Recordset
*iface
, REFIID riid
, void **obj
)
1284 struct recordset
*recordset
= impl_from_Recordset( iface
);
1285 TRACE( "%p, %s, %p\n", iface
, debugstr_guid(riid
), obj
);
1289 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDispatch
) ||
1290 IsEqualIID(riid
, &IID__ADO
) || IsEqualIID(riid
, &IID_Recordset15
) ||
1291 IsEqualIID(riid
, &IID_Recordset20
) || IsEqualIID(riid
, &IID_Recordset21
) ||
1292 IsEqualIID(riid
, &IID__Recordset
))
1296 else if (IsEqualGUID( riid
, &IID_ISupportErrorInfo
))
1298 *obj
= &recordset
->ISupportErrorInfo_iface
;
1300 else if (IsEqualGUID( riid
, &IID_ADORecordsetConstruction
))
1302 *obj
= &recordset
->ADORecordsetConstruction_iface
;
1304 else if (IsEqualGUID( riid
, &IID_IRunnableObject
))
1306 TRACE("IID_IRunnableObject not supported returning NULL\n");
1307 return E_NOINTERFACE
;
1311 FIXME( "interface %s not implemented\n", debugstr_guid(riid
) );
1312 return E_NOINTERFACE
;
1314 recordset_AddRef( iface
);
1318 static HRESULT WINAPI
recordset_GetTypeInfoCount( _Recordset
*iface
, UINT
*count
)
1320 struct recordset
*recordset
= impl_from_Recordset( iface
);
1321 TRACE( "%p, %p\n", recordset
, count
);
1326 static HRESULT WINAPI
recordset_GetTypeInfo( _Recordset
*iface
, UINT index
, LCID lcid
, ITypeInfo
**info
)
1328 struct recordset
*recordset
= impl_from_Recordset( iface
);
1329 TRACE( "%p, %u, %lu, %p\n", recordset
, index
, lcid
, info
);
1330 return get_typeinfo(Recordset_tid
, info
);
1333 static HRESULT WINAPI
recordset_GetIDsOfNames( _Recordset
*iface
, REFIID riid
, LPOLESTR
*names
, UINT count
,
1334 LCID lcid
, DISPID
*dispid
)
1336 struct recordset
*recordset
= impl_from_Recordset( iface
);
1338 ITypeInfo
*typeinfo
;
1340 TRACE( "%p, %s, %p, %u, %lu, %p\n", recordset
, debugstr_guid(riid
), names
, count
, lcid
, dispid
);
1342 hr
= get_typeinfo(Recordset_tid
, &typeinfo
);
1345 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, names
, count
, dispid
);
1346 ITypeInfo_Release(typeinfo
);
1352 static HRESULT WINAPI
recordset_Invoke( _Recordset
*iface
, DISPID member
, REFIID riid
, LCID lcid
, WORD flags
,
1353 DISPPARAMS
*params
, VARIANT
*result
, EXCEPINFO
*excep_info
, UINT
*arg_err
)
1355 struct recordset
*recordset
= impl_from_Recordset( iface
);
1357 ITypeInfo
*typeinfo
;
1359 TRACE( "%p, %ld, %s, %ld, %d, %p, %p, %p, %p\n", recordset
, member
, debugstr_guid(riid
), lcid
, flags
, params
,
1360 result
, excep_info
, arg_err
);
1362 hr
= get_typeinfo(Recordset_tid
, &typeinfo
);
1365 hr
= ITypeInfo_Invoke(typeinfo
, &recordset
->Recordset_iface
, member
, flags
, params
,
1366 result
, excep_info
, arg_err
);
1367 ITypeInfo_Release(typeinfo
);
1373 static HRESULT WINAPI
recordset_get_Properties( _Recordset
*iface
, Properties
**obj
)
1375 FIXME( "%p, %p\n", iface
, obj
);
1379 static HRESULT WINAPI
recordset_get_AbsolutePosition( _Recordset
*iface
, PositionEnum_Param
*pos
)
1381 FIXME( "%p, %p\n", iface
, pos
);
1385 static HRESULT WINAPI
recordset_put_AbsolutePosition( _Recordset
*iface
, PositionEnum_Param pos
)
1387 FIXME( "%p, %Id\n", iface
, pos
);
1391 static HRESULT WINAPI
recordset_putref_ActiveConnection( _Recordset
*iface
, IDispatch
*connection
)
1393 FIXME( "%p, %p\n", iface
, connection
);
1397 static HRESULT WINAPI
recordset_put_ActiveConnection( _Recordset
*iface
, VARIANT connection
)
1399 FIXME( "%p, %s\n", iface
, debugstr_variant(&connection
) );
1403 static HRESULT WINAPI
recordset_get_ActiveConnection( _Recordset
*iface
, VARIANT
*connection
)
1405 struct recordset
*recordset
= impl_from_Recordset( iface
);
1406 TRACE( "%p, %p\n", iface
, connection
);
1407 return VariantCopy(connection
, &recordset
->active_connection
);
1410 static HRESULT WINAPI
recordset_get_BOF( _Recordset
*iface
, VARIANT_BOOL
*bof
)
1412 struct recordset
*recordset
= impl_from_Recordset( iface
);
1414 TRACE( "%p, %p\n", recordset
, bof
);
1416 *bof
= (recordset
->index
< 0) ? VARIANT_TRUE
: VARIANT_FALSE
;
1420 static HRESULT WINAPI
recordset_get_Bookmark( _Recordset
*iface
, VARIANT
*bookmark
)
1422 struct recordset
*recordset
= impl_from_Recordset( iface
);
1423 TRACE( "%p, %p\n", iface
, bookmark
);
1425 if (recordset
->state
== adStateClosed
) return MAKE_ADO_HRESULT( adErrObjectClosed
);
1426 if (recordset
->index
< 0) return MAKE_ADO_HRESULT( adErrNoCurrentRecord
);
1428 V_VT(bookmark
) = VT_I4
;
1429 V_I4(bookmark
) = recordset
->index
;
1433 static HRESULT WINAPI
recordset_put_Bookmark( _Recordset
*iface
, VARIANT bookmark
)
1435 struct recordset
*recordset
= impl_from_Recordset( iface
);
1436 TRACE( "%p, %s\n", iface
, debugstr_variant(&bookmark
) );
1438 if (recordset
->state
== adStateClosed
) return MAKE_ADO_HRESULT( adErrObjectClosed
);
1440 if (V_VT(&bookmark
) != VT_I4
) return MAKE_ADO_HRESULT( adErrInvalidArgument
);
1442 recordset
->index
= V_I4(&bookmark
);
1446 static HRESULT WINAPI
recordset_get_CacheSize( _Recordset
*iface
, LONG
*size
)
1448 FIXME( "%p, %p\n", iface
, size
);
1452 static HRESULT WINAPI
recordset_put_CacheSize( _Recordset
*iface
, LONG size
)
1454 FIXME( "%p, %ld\n", iface
, size
);
1458 static HRESULT WINAPI
recordset_get_CursorType( _Recordset
*iface
, CursorTypeEnum
*cursor_type
)
1460 struct recordset
*recordset
= impl_from_Recordset( iface
);
1462 TRACE( "%p, %p\n", iface
, cursor_type
);
1464 *cursor_type
= recordset
->cursor_type
;
1468 static HRESULT WINAPI
recordset_put_CursorType( _Recordset
*iface
, CursorTypeEnum cursor_type
)
1470 struct recordset
*recordset
= impl_from_Recordset( iface
);
1472 TRACE( "%p, %d\n", iface
, cursor_type
);
1474 recordset
->cursor_type
= cursor_type
;
1478 static HRESULT WINAPI
recordset_get_EOF( _Recordset
*iface
, VARIANT_BOOL
*eof
)
1480 struct recordset
*recordset
= impl_from_Recordset( iface
);
1482 TRACE( "%p, %p\n", recordset
, eof
);
1484 *eof
= (!recordset
->count
|| recordset
->index
>= recordset
->count
) ? VARIANT_TRUE
: VARIANT_FALSE
;
1488 static HRESULT WINAPI
recordset_get_Fields( _Recordset
*iface
, Fields
**obj
)
1490 struct recordset
*recordset
= impl_from_Recordset( iface
);
1493 TRACE( "%p, %p\n", recordset
, obj
);
1495 if (recordset
->fields
)
1497 /* yes, this adds a reference to the recordset instead of the fields object */
1498 _Recordset_AddRef( &recordset
->Recordset_iface
);
1499 recordset
->fields
->recordset
= recordset
;
1500 *obj
= &recordset
->fields
->Fields_iface
;
1504 if ((hr
= fields_create( recordset
, &recordset
->fields
)) != S_OK
) return hr
;
1506 *obj
= &recordset
->fields
->Fields_iface
;
1510 static HRESULT WINAPI
recordset_get_LockType( _Recordset
*iface
, LockTypeEnum
*lock_type
)
1512 FIXME( "%p, %p\n", iface
, lock_type
);
1516 static HRESULT WINAPI
recordset_put_LockType( _Recordset
*iface
, LockTypeEnum lock_type
)
1518 FIXME( "%p, %d\n", iface
, lock_type
);
1522 static HRESULT WINAPI
recordset_get_MaxRecords( _Recordset
*iface
, ADO_LONGPTR
*max_records
)
1524 FIXME( "%p, %p\n", iface
, max_records
);
1528 static HRESULT WINAPI
recordset_put_MaxRecords( _Recordset
*iface
, ADO_LONGPTR max_records
)
1530 FIXME( "%p, %Id\n", iface
, max_records
);
1534 static HRESULT WINAPI
recordset_get_RecordCount( _Recordset
*iface
, ADO_LONGPTR
*count
)
1536 struct recordset
*recordset
= impl_from_Recordset( iface
);
1538 TRACE( "%p, %p\n", recordset
, count
);
1540 *count
= recordset
->count
;
1544 static HRESULT WINAPI
recordset_putref_Source( _Recordset
*iface
, IDispatch
*source
)
1546 FIXME( "%p, %p\n", iface
, source
);
1550 static HRESULT WINAPI
recordset_put_Source( _Recordset
*iface
, BSTR source
)
1552 FIXME( "%p, %s\n", iface
, debugstr_w(source
) );
1556 static HRESULT WINAPI
recordset_get_Source( _Recordset
*iface
, VARIANT
*source
)
1558 FIXME( "%p, %p\n", iface
, source
);
1562 static BOOL
resize_recordset( struct recordset
*recordset
, ULONG row_count
)
1564 ULONG row_size
= get_column_count( recordset
) * sizeof(*recordset
->data
);
1566 if (row_count
> recordset
->allocated
)
1569 ULONG count
= max( row_count
, recordset
->allocated
* 2 );
1570 if (!(tmp
= realloc( recordset
->data
, count
* row_size
))) return FALSE
;
1571 memset( tmp
+ recordset
->allocated
, 0, (count
- recordset
->allocated
) * row_size
);
1572 recordset
->data
= tmp
;
1573 recordset
->allocated
= count
;
1576 recordset
->count
= row_count
;
1580 static HRESULT WINAPI
recordset_AddNew( _Recordset
*iface
, VARIANT field_list
, VARIANT values
)
1582 struct recordset
*recordset
= impl_from_Recordset( iface
);
1584 TRACE( "%p, %s, %s\n", recordset
, debugstr_variant(&field_list
), debugstr_variant(&values
) );
1585 FIXME( "ignoring field list and values\n" );
1587 if (recordset
->state
== adStateClosed
) return MAKE_ADO_HRESULT( adErrObjectClosed
);
1589 if (!resize_recordset( recordset
, recordset
->count
+ 1 )) return E_OUTOFMEMORY
;
1590 recordset
->index
= recordset
->count
- 1;
1591 recordset
->editmode
= adEditAdd
;
1595 static HRESULT WINAPI
recordset_CancelUpdate( _Recordset
*iface
)
1597 struct recordset
*recordset
= impl_from_Recordset( iface
);
1599 FIXME( "%p\n", iface
);
1601 if (V_DISPATCH(&recordset
->active_connection
) == NULL
)
1604 recordset
->editmode
= adEditNone
;
1608 static HRESULT WINAPI
recordset_Close( _Recordset
*iface
)
1610 struct recordset
*recordset
= impl_from_Recordset( iface
);
1612 TRACE( "%p\n", recordset
);
1614 if (recordset
->state
== adStateClosed
) return MAKE_ADO_HRESULT( adErrObjectClosed
);
1616 close_recordset( recordset
);
1617 recordset
->state
= adStateClosed
;
1621 static HRESULT WINAPI
recordset_Delete( _Recordset
*iface
, AffectEnum affect_records
)
1623 FIXME( "%p, %u\n", iface
, affect_records
);
1627 static HRESULT WINAPI
recordset_GetRows( _Recordset
*iface
, LONG rows
, VARIANT start
, VARIANT fields
, VARIANT
*var
)
1629 FIXME( "%p, %ld, %s, %s, %p\n", iface
, rows
, debugstr_variant(&start
), debugstr_variant(&fields
), var
);
1633 static HRESULT WINAPI
recordset_Move( _Recordset
*iface
, ADO_LONGPTR num_records
, VARIANT start
)
1635 FIXME( "%p, %Id, %s\n", iface
, num_records
, debugstr_variant(&start
) );
1639 static HRESULT WINAPI
recordset_MoveNext( _Recordset
*iface
)
1641 struct recordset
*recordset
= impl_from_Recordset( iface
);
1643 TRACE( "%p\n", recordset
);
1645 if (recordset
->index
< recordset
->count
) recordset
->index
++;
1649 static HRESULT WINAPI
recordset_MovePrevious( _Recordset
*iface
)
1651 struct recordset
*recordset
= impl_from_Recordset( iface
);
1653 TRACE( "%p\n", recordset
);
1655 if (recordset
->index
>= 0) recordset
->index
--;
1659 static HRESULT WINAPI
recordset_MoveFirst( _Recordset
*iface
)
1661 struct recordset
*recordset
= impl_from_Recordset( iface
);
1663 TRACE( "%p\n", recordset
);
1665 recordset
->index
= 0;
1669 static HRESULT WINAPI
recordset_MoveLast( _Recordset
*iface
)
1671 struct recordset
*recordset
= impl_from_Recordset( iface
);
1673 TRACE( "%p\n", recordset
);
1675 recordset
->index
= (recordset
->count
> 0) ? recordset
->count
- 1 : 0;
1679 static HRESULT
create_command_text(IUnknown
*session
, BSTR command
, ICommandText
**cmd_text
)
1682 IOpenRowset
*openrowset
;
1683 ICommandText
*command_text
;
1685 IDBCreateCommand
*create_command
;
1687 hr
= IUnknown_QueryInterface(session
, &IID_IOpenRowset
, (void**)&openrowset
);
1691 hr
= IOpenRowset_QueryInterface(openrowset
, &IID_IDBCreateCommand
, (void**)&create_command
);
1692 IOpenRowset_Release(openrowset
);
1696 hr
= IDBCreateCommand_CreateCommand(create_command
, NULL
, &IID_IUnknown
, (IUnknown
**)&cmd
);
1697 IDBCreateCommand_Release(create_command
);
1701 hr
= ICommand_QueryInterface(cmd
, &IID_ICommandText
, (void**)&command_text
);
1702 ICommand_Release(cmd
);
1705 FIXME("Currently only ICommandText interface is support\n");
1709 hr
= ICommandText_SetCommandText(command_text
, &DBGUID_DEFAULT
, command
);
1712 ICommandText_Release(command_text
);
1716 *cmd_text
= command_text
;
1721 #define ROUND_SIZE(size) (((size) + sizeof(void *) - 1) & ~(sizeof(void *) - 1))
1723 DEFINE_GUID(DBPROPSET_ROWSET
, 0xc8b522be, 0x5cf3, 0x11ce, 0xad, 0xe5, 0x00, 0xaa, 0x00, 0x44, 0x77, 0x3d);
1725 static HRESULT
create_bindings(IUnknown
*rowset
, struct recordset
*recordset
, DBBINDING
**bind
, DBBYTEOFFSET
*size
)
1728 IColumnsInfo
*columninfo
;
1729 IAccessor
*accessor
;
1731 DBCOLUMNINFO
*colinfo
;
1732 OLECHAR
*stringsbuffer
;
1733 DBBINDING
*bindings
;
1734 DBBYTEOFFSET offset
;
1738 hr
= IUnknown_QueryInterface(rowset
, &IID_IColumnsInfo
, (void**)&columninfo
);
1742 hr
= IUnknown_QueryInterface(rowset
, &IID_IAccessor
, (void**)&accessor
);
1745 IColumnsInfo_Release(columninfo
);
1749 hr
= IColumnsInfo_GetColumnInfo(columninfo
, &columns
, &colinfo
, &stringsbuffer
);
1756 recordset
->columntypes
= malloc(sizeof(DBTYPE
) * columns
);
1757 recordset
->haccessors
= calloc(1, sizeof(HACCESSOR
) * columns
);
1759 /* Do one allocation for the bindings and append the DBOBJECTS to the end.
1760 * This is to save on multiple allocations vs a little bit of extra memory.
1762 bindings
= CoTaskMemAlloc( (sizeof(DBBINDING
) + sizeof(DBOBJECT
)) * columns
);
1763 dbobj
= (DBOBJECT
*)((char*)bindings
+ (sizeof(DBBINDING
) * columns
));
1765 for (i
=0; i
< columns
; i
++)
1767 TRACE("Column %lu, pwszName: %s, pTypeInfo %p, iOrdinal %Iu, dwFlags 0x%08lx, "
1768 "ulColumnSize %Iu, wType %d, bPrecision %d, bScale %d\n",
1769 i
, debugstr_w(colinfo
[i
].pwszName
), colinfo
[i
].pTypeInfo
, colinfo
[i
].iOrdinal
,
1770 colinfo
[i
].dwFlags
, colinfo
[i
].ulColumnSize
, colinfo
[i
].wType
,
1771 colinfo
[i
].bPrecision
, colinfo
[i
].bScale
);
1773 hr
= append_field(recordset
->fields
, colinfo
[i
].pwszName
, colinfo
[i
].wType
, colinfo
[i
].ulColumnSize
,
1774 colinfo
[i
].dwFlags
, NULL
);
1776 bindings
[i
].iOrdinal
= colinfo
[i
].iOrdinal
;
1777 bindings
[i
].obValue
= offset
;
1778 bindings
[i
].pTypeInfo
= NULL
;
1779 /* Always assigned the pObject even if it's not used. */
1780 bindings
[i
].pObject
= &dbobj
[i
];
1781 bindings
[i
].pObject
->dwFlags
= 0;
1782 bindings
[i
].pObject
->iid
= IID_ISequentialStream
;
1783 bindings
[i
].pBindExt
= NULL
;
1784 bindings
[i
].dwPart
= DBPART_VALUE
| DBPART_LENGTH
| DBPART_STATUS
;
1785 bindings
[i
].dwMemOwner
= DBMEMOWNER_CLIENTOWNED
;
1786 bindings
[i
].eParamIO
= 0;
1788 recordset
->columntypes
[i
] = colinfo
[i
].wType
;
1789 if (colinfo
[i
].dwFlags
& DBCOLUMNFLAGS_ISLONG
)
1791 colinfo
[i
].wType
= DBTYPE_IUNKNOWN
;
1793 bindings
[i
].cbMaxLen
= (colinfo
[i
].ulColumnSize
+ 1) * sizeof(WCHAR
);
1794 offset
+= sizeof(ISequentialStream
*);
1796 else if(colinfo
[i
].wType
== DBTYPE_WSTR
)
1798 /* ulColumnSize is the number of characters in the string not the actual buffer size */
1799 bindings
[i
].cbMaxLen
= colinfo
[i
].ulColumnSize
* sizeof(WCHAR
);
1800 offset
+= bindings
[i
].cbMaxLen
;
1804 bindings
[i
].cbMaxLen
= colinfo
[i
].ulColumnSize
;
1805 offset
+= bindings
[i
].cbMaxLen
;
1808 bindings
[i
].dwFlags
= 0;
1809 bindings
[i
].wType
= colinfo
[i
].wType
;
1810 bindings
[i
].bPrecision
= colinfo
[i
].bPrecision
;
1811 bindings
[i
].bScale
= colinfo
[i
].bScale
;
1814 offset
= ROUND_SIZE(offset
);
1815 for (i
=0; i
< columns
; i
++)
1817 bindings
[i
].obLength
= offset
;
1818 bindings
[i
].obStatus
= offset
+ sizeof(DBBYTEOFFSET
);
1820 offset
+= sizeof(DBBYTEOFFSET
) + sizeof(DBBYTEOFFSET
);
1822 hr
= IAccessor_CreateAccessor(accessor
, DBACCESSOR_ROWDATA
, 1, &bindings
[i
], 0, &recordset
->haccessors
[i
], NULL
);
1824 FIXME("IAccessor_CreateAccessor Failed 0x%0lx\n", hr
);
1830 CoTaskMemFree(colinfo
);
1831 CoTaskMemFree(stringsbuffer
);
1834 IAccessor_Release(accessor
);
1836 IColumnsInfo_Release(columninfo
);
1841 static HRESULT
load_all_recordset_data(struct recordset
*recordset
, IUnknown
*rowset
, DBBINDING
*bindings
,
1842 DBBYTEOFFSET datasize
)
1847 DBCOUNTITEM obtained
;
1849 int datarow
= 0, datacol
;
1852 columns
= get_column_count(recordset
);
1854 /* Create the data array */
1855 if (!resize_recordset( recordset
, recordset
->count
))
1857 WARN("Failed to resize recordset\n");
1858 return E_OUTOFMEMORY
;
1861 hr
= IUnknown_QueryInterface(rowset
, &IID_IRowset
, (void**)&rowset2
);
1864 WARN("Failed to get IRowset interface (0x%08lx)\n", hr
);
1868 data
= malloc (datasize
);
1871 ERR("Failed to allocate row data (%Iu)\n", datasize
);
1872 IRowset_Release(rowset2
);
1873 return E_OUTOFMEMORY
;
1876 hr
= IRowset_GetNextRows(rowset2
, 0, 0, 1, &obtained
, &row
);
1881 for (datacol
= 0; datacol
< columns
; datacol
++)
1883 hr
= IRowset_GetData(rowset2
, *row
, recordset
->haccessors
[datacol
], data
);
1886 ERR("GetData Failed on Column %d (0x%08lx), status %Id\n", datacol
, hr
,
1887 *(DBBYTEOFFSET
*)(data
+ bindings
[datacol
].obStatus
));
1893 if ( *(DBBYTEOFFSET
*)(data
+ bindings
[datacol
].obStatus
) == DBSTATUS_S_ISNULL
)
1895 V_VT(©
) = VT_NULL
;
1899 /* For most cases DBTYPE_* = VT_* type */
1900 V_VT(©
) = bindings
[datacol
].wType
;
1901 switch(bindings
[datacol
].wType
)
1903 case DBTYPE_IUNKNOWN
:
1905 ISequentialStream
*seq
;
1907 ULONG size
= 4096, dataRead
= 0, total
= 0;
1908 char *buffer
= malloc(size
), *p
= buffer
;
1912 * Cast directly to the object we specified in our bindings. As this object
1913 * is referenced counted in some case and will error in GetData if the object
1914 * hasn't been released.
1916 seq
= *(ISequentialStream
**)(data
+ bindings
[datacol
].obValue
);
1917 TRACE("Reading DBTYPE_IUNKNOWN %p\n", seq
);
1922 hr2
= ISequentialStream_Read(seq
, unkdata
, sizeof(unkdata
), &dataRead
);
1923 if (FAILED(hr2
) || !dataRead
) break;
1926 memcpy(p
, unkdata
, dataRead
);
1930 size
*= 2; /* Double buffer */
1931 buffer
= realloc(buffer
, size
);
1934 } while(hr2
== S_OK
);
1936 if (recordset
->columntypes
[datacol
] == DBTYPE_WSTR
)
1938 V_VT(©
) = VT_BSTR
;
1939 V_BSTR(©
) = SysAllocStringLen( (WCHAR
*)buffer
, total
/ sizeof(WCHAR
) );
1941 else if (recordset
->columntypes
[datacol
] == DBTYPE_BYTES
)
1946 sab
.cElements
= total
;
1948 V_VT(©
) = (VT_ARRAY
|VT_UI1
);
1949 V_ARRAY(©
) = SafeArrayCreate(VT_UI1
, 1, &sab
);
1951 memcpy( (BYTE
*)V_ARRAY(©
)->pvData
, buffer
, total
);
1955 FIXME("Unsupported conversion (%d)\n", recordset
->columntypes
[datacol
]);
1956 V_VT(©
) = VT_NULL
;
1960 ISequentialStream_Release(seq
);
1965 V_R4(©
) = *(float*)(data
+ bindings
[datacol
].obValue
);
1968 V_R8(©
) = *(DOUBLE
*)(data
+ bindings
[datacol
].obValue
);
1971 V_VT(©
) = VT_I8
;
1972 V_I8(©
) = *(LONGLONG
*)(data
+ bindings
[datacol
].obValue
);
1975 V_I4(©
) = *(LONG
*)(data
+ bindings
[datacol
].obValue
);
1979 WCHAR
*str
= heap_strdupAtoW( (char*)(data
+ bindings
[datacol
].obValue
) );
1981 V_VT(©
) = VT_BSTR
;
1982 V_BSTR(©
) = SysAllocString(str
);
1988 V_VT(©
) = VT_BSTR
;
1989 V_BSTR(©
) = SysAllocString( (WCHAR
*)(data
+ bindings
[datacol
].obValue
) );
1992 case DBTYPE_DBTIMESTAMP
:
1995 DBTIMESTAMP
*ts
= (DBTIMESTAMP
*)(data
+ bindings
[datacol
].obValue
);
1998 V_VT(©
) = VT_DATE
;
2000 st
.wYear
= ts
->year
;
2001 st
.wMonth
= ts
->month
;
2003 st
.wHour
= ts
->hour
;
2004 st
.wMinute
= ts
->minute
;
2005 st
.wSecond
= ts
->second
;
2006 st
.wMilliseconds
= ts
->fraction
/1000000;
2008 hr
= (SystemTimeToVariantTime(&st
, &d
) ? S_OK
: E_FAIL
);
2015 FIXME("Unknown Type %d\n", bindings
[datacol
].wType
);
2019 VariantInit( &recordset
->data
[datarow
* columns
+ datacol
] );
2020 if ((hr
= VariantCopy( &recordset
->data
[datarow
* columns
+ datacol
] , ©
)) != S_OK
)
2022 ERR("Column %d copy failed. Data %s\n", datacol
, debugstr_variant(©
));
2025 VariantClear(©
);
2030 hr
= IRowset_ReleaseRows(rowset2
, 1, row
, NULL
, NULL
, NULL
);
2032 ERR("Failed to ReleaseRows 0x%08lx\n", hr
);
2034 hr
= IRowset_GetNextRows(rowset2
, 0, 0, 1, &obtained
, &row
);
2038 IRowset_Release(rowset2
);
2043 static HRESULT WINAPI
recordset_Open( _Recordset
*iface
, VARIANT source
, VARIANT active_connection
,
2044 CursorTypeEnum cursor_type
, LockTypeEnum lock_type
, LONG options
)
2046 struct recordset
*recordset
= impl_from_Recordset( iface
);
2047 ADOConnectionConstruction15
*construct
;
2049 ICommandText
*command_text
;
2050 DBROWCOUNT affected
;
2053 DBBINDING
*bindings
;
2054 DBBYTEOFFSET datasize
;
2056 TRACE( "%p, %s, %s, %d, %d, %ld\n", recordset
, debugstr_variant(&source
), debugstr_variant(&active_connection
),
2057 cursor_type
, lock_type
, options
);
2059 if (recordset
->state
== adStateOpen
) return MAKE_ADO_HRESULT( adErrObjectOpen
);
2061 if (recordset
->fields
)
2063 recordset
->state
= adStateOpen
;
2067 if (V_VT(&active_connection
) != VT_DISPATCH
)
2069 FIXME("Unsupported Active connection type %d\n", V_VT(&active_connection
));
2070 return MAKE_ADO_HRESULT( adErrInvalidConnection
);
2073 hr
= IDispatch_QueryInterface(V_DISPATCH(&active_connection
), &IID_ADOConnectionConstruction15
, (void**)&construct
);
2077 hr
= ADOConnectionConstruction15_get_Session(construct
, &session
);
2078 ADOConnectionConstruction15_Release(construct
);
2082 hr
= VariantCopy(&recordset
->active_connection
, &active_connection
);
2086 if (V_VT(&source
) != VT_BSTR
)
2088 FIXME("Unsupported source type!\n");
2089 IUnknown_Release(session
);
2093 hr
= create_command_text(session
, V_BSTR(&source
), &command_text
);
2094 IUnknown_Release(session
);
2098 hr
= ICommandText_Execute(command_text
, NULL
, &IID_IUnknown
, NULL
, &affected
, &rowset
);
2099 ICommandText_Release(command_text
);
2100 if (FAILED(hr
) || !rowset
)
2103 /* We want to create the field member variable without mapping the rowset fields, this will
2104 * save querying the fields twice. Fields will be added while we create the bindings.
2106 hr
= fields_create( recordset
, &recordset
->fields
);
2109 IUnknown_Release(rowset
);
2113 hr
= create_bindings(rowset
, recordset
, &bindings
, &datasize
);
2116 WARN("Failed to load bindings (%lx)\n", hr
);
2117 IUnknown_Release(rowset
);
2121 recordset
->count
= affected
> 0 ? affected
: 0;
2122 recordset
->index
= affected
> 0 ? 0 : -1;
2125 * We can safely just return with an empty recordset here
2129 hr
= load_all_recordset_data(recordset
, rowset
, bindings
, datasize
);
2132 WARN("Failed to load all recordset data (%lx)\n", hr
);
2133 CoTaskMemFree(bindings
);
2134 IUnknown_Release(rowset
);
2139 CoTaskMemFree(bindings
);
2141 ADORecordsetConstruction_put_Rowset(&recordset
->ADORecordsetConstruction_iface
, rowset
);
2142 recordset
->cursor_type
= cursor_type
;
2143 recordset
->state
= adStateOpen
;
2145 IUnknown_Release(rowset
);
2150 static HRESULT WINAPI
recordset_Requery( _Recordset
*iface
, LONG options
)
2152 FIXME( "%p, %ld\n", iface
, options
);
2156 static HRESULT WINAPI
recordset__xResync( _Recordset
*iface
, AffectEnum affect_records
)
2158 FIXME( "%p, %u\n", iface
, affect_records
);
2162 static HRESULT WINAPI
recordset_Update( _Recordset
*iface
, VARIANT fields
, VARIANT values
)
2164 struct recordset
*recordset
= impl_from_Recordset( iface
);
2166 FIXME( "%p, %s, %s\n", iface
, debugstr_variant(&fields
), debugstr_variant(&values
) );
2168 if (V_DISPATCH(&recordset
->active_connection
) == NULL
)
2171 recordset
->editmode
= adEditNone
;
2175 static HRESULT WINAPI
recordset_get_AbsolutePage( _Recordset
*iface
, PositionEnum_Param
*pos
)
2177 FIXME( "%p, %p\n", iface
, pos
);
2181 static HRESULT WINAPI
recordset_put_AbsolutePage( _Recordset
*iface
, PositionEnum_Param pos
)
2183 FIXME( "%p, %Id\n", iface
, pos
);
2187 static HRESULT WINAPI
recordset_get_EditMode( _Recordset
*iface
, EditModeEnum
*mode
)
2189 struct recordset
*recordset
= impl_from_Recordset( iface
);
2190 TRACE( "%p, %p\n", iface
, mode
);
2192 if (recordset
->state
== adStateClosed
) return MAKE_ADO_HRESULT( adErrObjectClosed
);
2193 if (recordset
->index
< 0) return MAKE_ADO_HRESULT( adErrNoCurrentRecord
);
2195 *mode
= recordset
->editmode
;
2199 static HRESULT WINAPI
recordset_get_Filter( _Recordset
*iface
, VARIANT
*criteria
)
2201 struct recordset
*recordset
= impl_from_Recordset( iface
);
2202 TRACE( "%p, %p\n", iface
, criteria
);
2204 if (!criteria
) return MAKE_ADO_HRESULT( adErrInvalidArgument
);
2206 VariantCopy(criteria
, &recordset
->filter
);
2210 static HRESULT WINAPI
recordset_put_Filter( _Recordset
*iface
, VARIANT criteria
)
2212 struct recordset
*recordset
= impl_from_Recordset( iface
);
2213 TRACE( "%p, %s\n", recordset
, debugstr_variant(&criteria
) );
2215 if (V_VT(&criteria
) != VT_I2
&& V_VT(&criteria
) != VT_I4
&& V_VT(&criteria
) != VT_BSTR
)
2216 return MAKE_ADO_HRESULT( adErrInvalidArgument
);
2218 if (V_VT(&criteria
) == VT_BSTR
&& recordset
->state
== adStateOpen
)
2220 FIXME("No filter performed. Reporting no records found.\n");
2222 /* Set the index to signal we didn't find a record. */
2223 recordset
->index
= -1;
2227 recordset
->index
= recordset
->count
? 0 : -1; /* Reset */
2230 VariantCopy(&recordset
->filter
, &criteria
);
2234 static HRESULT WINAPI
recordset_get_PageCount( _Recordset
*iface
, ADO_LONGPTR
*count
)
2236 FIXME( "%p, %p\n", iface
, count
);
2240 static HRESULT WINAPI
recordset_get_PageSize( _Recordset
*iface
, LONG
*size
)
2242 FIXME( "%p, %p\n", iface
, size
);
2246 static HRESULT WINAPI
recordset_put_PageSize( _Recordset
*iface
, LONG size
)
2248 FIXME( "%p, %ld\n", iface
, size
);
2252 static HRESULT WINAPI
recordset_get_Sort( _Recordset
*iface
, BSTR
*criteria
)
2254 FIXME( "%p, %p\n", iface
, criteria
);
2258 static HRESULT WINAPI
recordset_put_Sort( _Recordset
*iface
, BSTR criteria
)
2260 FIXME( "%p, %s\n", iface
, debugstr_w(criteria
) );
2264 static HRESULT WINAPI
recordset_get_Status( _Recordset
*iface
, LONG
*status
)
2266 FIXME( "%p, %p\n", iface
, status
);
2270 static HRESULT WINAPI
recordset_get_State( _Recordset
*iface
, LONG
*state
)
2272 struct recordset
*recordset
= impl_from_Recordset( iface
);
2274 TRACE( "%p, %p\n", recordset
, state
);
2276 *state
= recordset
->state
;
2280 static HRESULT WINAPI
recordset__xClone( _Recordset
*iface
, _Recordset
**obj
)
2282 FIXME( "%p, %p\n", iface
, obj
);
2286 static HRESULT WINAPI
recordset_UpdateBatch( _Recordset
*iface
, AffectEnum affect_records
)
2288 struct recordset
*recordset
= impl_from_Recordset( iface
);
2290 FIXME( "%p, %u\n", iface
, affect_records
);
2292 if (V_DISPATCH(&recordset
->active_connection
) == NULL
)
2295 recordset
->editmode
= adEditNone
;
2299 static HRESULT WINAPI
recordset_CancelBatch( _Recordset
*iface
, AffectEnum affect_records
)
2301 struct recordset
*recordset
= impl_from_Recordset( iface
);
2303 FIXME( "%p, %u\n", iface
, affect_records
);
2305 if (V_DISPATCH(&recordset
->active_connection
) == NULL
)
2308 recordset
->editmode
= adEditNone
;
2312 static HRESULT WINAPI
recordset_get_CursorLocation( _Recordset
*iface
, CursorLocationEnum
*cursor_loc
)
2314 struct recordset
*recordset
= impl_from_Recordset( iface
);
2316 TRACE( "%p, %p\n", iface
, cursor_loc
);
2318 *cursor_loc
= recordset
->cursor_location
;
2323 static HRESULT WINAPI
recordset_put_CursorLocation( _Recordset
*iface
, CursorLocationEnum cursor_loc
)
2325 struct recordset
*recordset
= impl_from_Recordset( iface
);
2327 TRACE( "%p, %u\n", iface
, cursor_loc
);
2329 if (recordset
->state
== adStateOpen
) return MAKE_ADO_HRESULT( adErrObjectOpen
);
2331 recordset
->cursor_location
= cursor_loc
;
2336 static HRESULT WINAPI
recordset_NextRecordset( _Recordset
*iface
, VARIANT
*records_affected
, _Recordset
**record_set
)
2338 FIXME( "%p, %p, %p\n", iface
, records_affected
, record_set
);
2342 static HRESULT WINAPI
recordset_Supports( _Recordset
*iface
, CursorOptionEnum cursor_options
, VARIANT_BOOL
*ret
)
2344 FIXME( "%p, %08x, %p\n", iface
, cursor_options
, ret
);
2348 static HRESULT WINAPI
recordset_get_Collect( _Recordset
*iface
, VARIANT index
, VARIANT
*var
)
2350 FIXME( "%p, %s, %p\n", iface
, debugstr_variant(&index
), var
);
2354 static HRESULT WINAPI
recordset_put_Collect( _Recordset
*iface
, VARIANT index
, VARIANT var
)
2356 FIXME( "%p, %s, %s\n", iface
, debugstr_variant(&index
), debugstr_variant(&var
) );
2360 static HRESULT WINAPI
recordset_get_MarshalOptions( _Recordset
*iface
, MarshalOptionsEnum
*options
)
2362 FIXME( "%p, %p\n", iface
, options
);
2366 static HRESULT WINAPI
recordset_put_MarshalOptions( _Recordset
*iface
, MarshalOptionsEnum options
)
2368 FIXME( "%p, %u\n", iface
, options
);
2372 static HRESULT WINAPI
recordset_Find( _Recordset
*iface
, BSTR criteria
, LONG skip_records
,
2373 SearchDirectionEnum search_direction
, VARIANT start
)
2375 FIXME( "%p, %s, %ld, %d, %s\n", iface
, debugstr_w(criteria
), skip_records
, search_direction
,
2376 debugstr_variant(&start
) );
2380 static HRESULT WINAPI
recordset_Cancel( _Recordset
*iface
)
2382 struct recordset
*recordset
= impl_from_Recordset( iface
);
2384 FIXME( "%p\n", iface
);
2386 if (V_DISPATCH(&recordset
->active_connection
) == NULL
)
2389 recordset
->editmode
= adEditNone
;
2393 static HRESULT WINAPI
recordset_get_DataSource( _Recordset
*iface
, IUnknown
**data_source
)
2395 FIXME( "%p, %p\n", iface
, data_source
);
2399 static HRESULT WINAPI
recordset_putref_DataSource( _Recordset
*iface
, IUnknown
*data_source
)
2401 FIXME( "%p, %p\n", iface
, data_source
);
2405 static HRESULT WINAPI
recordset__xSave( _Recordset
*iface
, BSTR filename
, PersistFormatEnum persist_format
)
2407 FIXME( "%p, %s, %u\n", iface
, debugstr_w(filename
), persist_format
);
2411 static HRESULT WINAPI
recordset_get_ActiveCommand( _Recordset
*iface
, IDispatch
**cmd
)
2413 FIXME( "%p, %p\n", iface
, cmd
);
2417 static HRESULT WINAPI
recordset_put_StayInSync( _Recordset
*iface
, VARIANT_BOOL stay_in_sync
)
2419 FIXME( "%p, %d\n", iface
, stay_in_sync
);
2423 static HRESULT WINAPI
recordset_get_StayInSync( _Recordset
*iface
, VARIANT_BOOL
*stay_in_sync
)
2425 FIXME( "%p, %p\n", iface
, stay_in_sync
);
2429 static HRESULT WINAPI
recordset_GetString( _Recordset
*iface
, StringFormatEnum string_format
, LONG num_rows
,
2430 BSTR column_delimiter
, BSTR row_delimiter
, BSTR null_expr
,
2433 FIXME( "%p, %u, %ld, %s, %s, %s, %p\n", iface
, string_format
, num_rows
, debugstr_w(column_delimiter
),
2434 debugstr_w(row_delimiter
), debugstr_w(null_expr
), ret_string
);
2438 static HRESULT WINAPI
recordset_get_DataMember( _Recordset
*iface
, BSTR
*data_member
)
2440 FIXME( "%p, %p\n", iface
, data_member
);
2444 static HRESULT WINAPI
recordset_put_DataMember( _Recordset
*iface
, BSTR data_member
)
2446 FIXME( "%p, %s\n", iface
, debugstr_w(data_member
) );
2450 static HRESULT WINAPI
recordset_CompareBookmarks( _Recordset
*iface
, VARIANT bookmark1
, VARIANT bookmark2
, CompareEnum
*compare
)
2452 FIXME( "%p, %s, %s, %p\n", iface
, debugstr_variant(&bookmark1
), debugstr_variant(&bookmark2
), compare
);
2456 static HRESULT WINAPI
recordset_Clone( _Recordset
*iface
, LockTypeEnum lock_type
, _Recordset
**obj
)
2458 struct recordset
*recordset
= impl_from_Recordset( iface
);
2459 FIXME( "%p, %d, %p\n", recordset
, lock_type
, obj
);
2462 recordset_AddRef( iface
);
2466 static HRESULT WINAPI
recordset_Resync( _Recordset
*iface
, AffectEnum affect_records
, ResyncEnum resync_values
)
2468 FIXME( "%p, %u, %u\n", iface
, affect_records
, resync_values
);
2472 static HRESULT WINAPI
recordset_Seek( _Recordset
*iface
, VARIANT key_values
, SeekEnum seek_option
)
2474 FIXME( "%p, %s, %u\n", iface
, debugstr_variant(&key_values
), seek_option
);
2478 static HRESULT WINAPI
recordset_put_Index( _Recordset
*iface
, BSTR index
)
2480 FIXME( "%p, %s\n", iface
, debugstr_w(index
) );
2484 static HRESULT WINAPI
recordset_get_Index( _Recordset
*iface
, BSTR
*index
)
2486 FIXME( "%p, %p\n", iface
, index
);
2490 static HRESULT WINAPI
recordset_Save( _Recordset
*iface
, VARIANT destination
, PersistFormatEnum persist_format
)
2492 FIXME( "%p, %s, %u\n", iface
, debugstr_variant(&destination
), persist_format
);
2496 static const struct _RecordsetVtbl recordset_vtbl
=
2498 recordset_QueryInterface
,
2501 recordset_GetTypeInfoCount
,
2502 recordset_GetTypeInfo
,
2503 recordset_GetIDsOfNames
,
2505 recordset_get_Properties
,
2506 recordset_get_AbsolutePosition
,
2507 recordset_put_AbsolutePosition
,
2508 recordset_putref_ActiveConnection
,
2509 recordset_put_ActiveConnection
,
2510 recordset_get_ActiveConnection
,
2512 recordset_get_Bookmark
,
2513 recordset_put_Bookmark
,
2514 recordset_get_CacheSize
,
2515 recordset_put_CacheSize
,
2516 recordset_get_CursorType
,
2517 recordset_put_CursorType
,
2519 recordset_get_Fields
,
2520 recordset_get_LockType
,
2521 recordset_put_LockType
,
2522 recordset_get_MaxRecords
,
2523 recordset_put_MaxRecords
,
2524 recordset_get_RecordCount
,
2525 recordset_putref_Source
,
2526 recordset_put_Source
,
2527 recordset_get_Source
,
2529 recordset_CancelUpdate
,
2535 recordset_MovePrevious
,
2536 recordset_MoveFirst
,
2542 recordset_get_AbsolutePage
,
2543 recordset_put_AbsolutePage
,
2544 recordset_get_EditMode
,
2545 recordset_get_Filter
,
2546 recordset_put_Filter
,
2547 recordset_get_PageCount
,
2548 recordset_get_PageSize
,
2549 recordset_put_PageSize
,
2552 recordset_get_Status
,
2553 recordset_get_State
,
2555 recordset_UpdateBatch
,
2556 recordset_CancelBatch
,
2557 recordset_get_CursorLocation
,
2558 recordset_put_CursorLocation
,
2559 recordset_NextRecordset
,
2561 recordset_get_Collect
,
2562 recordset_put_Collect
,
2563 recordset_get_MarshalOptions
,
2564 recordset_put_MarshalOptions
,
2567 recordset_get_DataSource
,
2568 recordset_putref_DataSource
,
2570 recordset_get_ActiveCommand
,
2571 recordset_put_StayInSync
,
2572 recordset_get_StayInSync
,
2573 recordset_GetString
,
2574 recordset_get_DataMember
,
2575 recordset_put_DataMember
,
2576 recordset_CompareBookmarks
,
2580 recordset_put_Index
,
2581 recordset_get_Index
,
2585 static inline struct recordset
*recordset_from_ISupportErrorInfo( ISupportErrorInfo
*iface
)
2587 return CONTAINING_RECORD( iface
, struct recordset
, ISupportErrorInfo_iface
);
2590 static HRESULT WINAPI
recordset_supporterrorinfo_QueryInterface( ISupportErrorInfo
*iface
, REFIID riid
, void **obj
)
2592 struct recordset
*recordset
= recordset_from_ISupportErrorInfo( iface
);
2593 return _Recordset_QueryInterface( &recordset
->Recordset_iface
, riid
, obj
);
2596 static ULONG WINAPI
recordset_supporterrorinfo_AddRef( ISupportErrorInfo
*iface
)
2598 struct recordset
*recordset
= recordset_from_ISupportErrorInfo( iface
);
2599 return _Recordset_AddRef( &recordset
->Recordset_iface
);
2602 static ULONG WINAPI
recordset_supporterrorinfo_Release( ISupportErrorInfo
*iface
)
2604 struct recordset
*recordset
= recordset_from_ISupportErrorInfo( iface
);
2605 return _Recordset_Release( &recordset
->Recordset_iface
);
2608 static HRESULT WINAPI
recordset_supporterrorinfo_InterfaceSupportsErrorInfo( ISupportErrorInfo
*iface
, REFIID riid
)
2610 struct recordset
*recordset
= recordset_from_ISupportErrorInfo( iface
);
2611 FIXME( "%p, %s\n", recordset
, debugstr_guid(riid
) );
2615 static const ISupportErrorInfoVtbl recordset_supporterrorinfo_vtbl
=
2617 recordset_supporterrorinfo_QueryInterface
,
2618 recordset_supporterrorinfo_AddRef
,
2619 recordset_supporterrorinfo_Release
,
2620 recordset_supporterrorinfo_InterfaceSupportsErrorInfo
2623 static HRESULT WINAPI
rsconstruction_QueryInterface(ADORecordsetConstruction
*iface
,
2624 REFIID riid
, void **obj
)
2626 struct recordset
*recordset
= impl_from_ADORecordsetConstruction( iface
);
2627 return _Recordset_QueryInterface( &recordset
->Recordset_iface
, riid
, obj
);
2630 static ULONG WINAPI
rsconstruction_AddRef(ADORecordsetConstruction
*iface
)
2632 struct recordset
*recordset
= impl_from_ADORecordsetConstruction( iface
);
2633 return _Recordset_AddRef( &recordset
->Recordset_iface
);
2636 static ULONG WINAPI
rsconstruction_Release(ADORecordsetConstruction
*iface
)
2638 struct recordset
*recordset
= impl_from_ADORecordsetConstruction( iface
);
2639 return _Recordset_Release( &recordset
->Recordset_iface
);
2642 static HRESULT WINAPI
rsconstruction_GetTypeInfoCount(ADORecordsetConstruction
*iface
, UINT
*pctinfo
)
2644 struct recordset
*recordset
= impl_from_ADORecordsetConstruction( iface
);
2645 TRACE( "%p, %p\n", recordset
, pctinfo
);
2650 static HRESULT WINAPI
rsconstruction_GetTypeInfo(ADORecordsetConstruction
*iface
, UINT iTInfo
,
2651 LCID lcid
, ITypeInfo
**ppTInfo
)
2653 struct recordset
*recordset
= impl_from_ADORecordsetConstruction( iface
);
2654 TRACE( "%p %u %lu %p\n", recordset
, iTInfo
, lcid
, ppTInfo
);
2655 return get_typeinfo(ADORecordsetConstruction_tid
, ppTInfo
);
2658 static HRESULT WINAPI
rsconstruction_GetIDsOfNames(ADORecordsetConstruction
*iface
, REFIID riid
,
2659 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
2661 struct recordset
*recordset
= impl_from_ADORecordsetConstruction( iface
);
2663 ITypeInfo
*typeinfo
;
2665 TRACE( "%p %s %p %u %lu %p\n", recordset
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
2667 hr
= get_typeinfo(ADORecordsetConstruction_tid
, &typeinfo
);
2670 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2671 ITypeInfo_Release(typeinfo
);
2677 static HRESULT WINAPI
rsconstruction_Invoke(ADORecordsetConstruction
*iface
, DISPID dispIdMember
,
2678 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
2679 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2681 struct recordset
*recordset
= impl_from_ADORecordsetConstruction( iface
);
2683 ITypeInfo
*typeinfo
;
2685 TRACE( "%p %ld %s %ld %d %p %p %p %p\n", recordset
, dispIdMember
, debugstr_guid(riid
),
2686 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2688 hr
= get_typeinfo(ADORecordsetConstruction_tid
, &typeinfo
);
2691 hr
= ITypeInfo_Invoke(typeinfo
, &recordset
->ADORecordsetConstruction_iface
, dispIdMember
, wFlags
,
2692 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2693 ITypeInfo_Release(typeinfo
);
2699 static HRESULT WINAPI
rsconstruction_get_Rowset(ADORecordsetConstruction
*iface
, IUnknown
**row_set
)
2701 struct recordset
*recordset
= impl_from_ADORecordsetConstruction( iface
);
2704 TRACE( "%p, %p\n", recordset
, row_set
);
2706 hr
= IRowset_QueryInterface(recordset
->row_set
, &IID_IUnknown
, (void**)row_set
);
2707 if ( FAILED(hr
) ) return E_FAIL
;
2712 static HRESULT WINAPI
rsconstruction_put_Rowset(ADORecordsetConstruction
*iface
, IUnknown
*unk
)
2714 struct recordset
*recordset
= impl_from_ADORecordsetConstruction( iface
);
2718 TRACE( "%p, %p\n", recordset
, unk
);
2720 hr
= IUnknown_QueryInterface(unk
, &IID_IRowset
, (void**)&rowset
);
2721 if ( FAILED(hr
) ) return E_FAIL
;
2723 if ( recordset
->row_set
) IRowset_Release( recordset
->row_set
);
2724 recordset
->row_set
= rowset
;
2729 static HRESULT WINAPI
rsconstruction_get_Chapter(ADORecordsetConstruction
*iface
, ADO_LONGPTR
*chapter
)
2731 struct recordset
*recordset
= impl_from_ADORecordsetConstruction( iface
);
2732 FIXME( "%p, %p\n", recordset
, chapter
);
2736 static HRESULT WINAPI
rsconstruction_put_Chapter(ADORecordsetConstruction
*iface
, ADO_LONGPTR chapter
)
2738 struct recordset
*recordset
= impl_from_ADORecordsetConstruction( iface
);
2739 FIXME( "%p, %Id\n", recordset
, chapter
);
2743 static HRESULT WINAPI
rsconstruction_get_RowPosition(ADORecordsetConstruction
*iface
, IUnknown
**row_pos
)
2745 struct recordset
*recordset
= impl_from_ADORecordsetConstruction( iface
);
2746 FIXME( "%p, %p\n", recordset
, row_pos
);
2750 static HRESULT WINAPI
rsconstruction_put_RowPosition(ADORecordsetConstruction
*iface
, IUnknown
*row_pos
)
2752 struct recordset
*recordset
= impl_from_ADORecordsetConstruction( iface
);
2753 FIXME( "%p, %p\n", recordset
, row_pos
);
2757 static const ADORecordsetConstructionVtbl rsconstruction_vtbl
=
2759 rsconstruction_QueryInterface
,
2760 rsconstruction_AddRef
,
2761 rsconstruction_Release
,
2762 rsconstruction_GetTypeInfoCount
,
2763 rsconstruction_GetTypeInfo
,
2764 rsconstruction_GetIDsOfNames
,
2765 rsconstruction_Invoke
,
2766 rsconstruction_get_Rowset
,
2767 rsconstruction_put_Rowset
,
2768 rsconstruction_get_Chapter
,
2769 rsconstruction_put_Chapter
,
2770 rsconstruction_get_RowPosition
,
2771 rsconstruction_put_RowPosition
2774 HRESULT
Recordset_create( void **obj
)
2776 struct recordset
*recordset
;
2778 if (!(recordset
= calloc( 1, sizeof(*recordset
) ))) return E_OUTOFMEMORY
;
2779 recordset
->Recordset_iface
.lpVtbl
= &recordset_vtbl
;
2780 recordset
->ISupportErrorInfo_iface
.lpVtbl
= &recordset_supporterrorinfo_vtbl
;
2781 recordset
->ADORecordsetConstruction_iface
.lpVtbl
= &rsconstruction_vtbl
;
2782 V_VT(&recordset
->active_connection
) = VT_DISPATCH
;
2783 V_DISPATCH(&recordset
->active_connection
) = NULL
;
2784 recordset
->refs
= 1;
2785 recordset
->index
= -1;
2786 recordset
->cursor_location
= adUseServer
;
2787 recordset
->cursor_type
= adOpenForwardOnly
;
2788 recordset
->row_set
= NULL
;
2789 recordset
->editmode
= adEditNone
;
2790 VariantInit( &recordset
->filter
);
2791 recordset
->columntypes
= NULL
;
2792 recordset
->haccessors
= NULL
;
2794 *obj
= &recordset
->Recordset_iface
;
2795 TRACE( "returning iface %p\n", *obj
);