From: Piotr Caban piotr@codeweavers.com
--- dlls/msado15/recordset.c | 86 +++++++++++++++++++++++++++++++++++- dlls/msado15/tests/msado15.c | 37 +++++++++++++++- 2 files changed, 119 insertions(+), 4 deletions(-)
diff --git a/dlls/msado15/recordset.c b/dlls/msado15/recordset.c index 5dcf98269d7..ffe3b2168b3 100644 --- a/dlls/msado15/recordset.c +++ b/dlls/msado15/recordset.c @@ -120,6 +120,9 @@ struct recordset HACCESSOR bookmark_hacc; DBTYPE bookmark_type; VARIANT bookmark; + + ULONG prop_count; + DBPROPSET *prop; };
static inline struct field *impl_from_Field( Field *iface ) @@ -1609,7 +1612,7 @@ static ULONG WINAPI recordset_AddRef( _Recordset *iface )
static void close_recordset( struct recordset *recordset ) { - int i; + int i, j;
cache_release( recordset ); recordset->is_bof = recordset->is_eof = VARIANT_FALSE; @@ -1659,6 +1662,16 @@ static void close_recordset( struct recordset *recordset ) if (recordset->accessor && recordset->accessor != NO_INTERFACE ) IAccessor_Release( recordset->accessor ); recordset->accessor = NULL; + + for (i = 0; i < recordset->prop_count; i++) + { + for (j = 0; j < recordset->prop[i].cProperties; j++) + VariantClear( &recordset->prop[i].rgProperties[j].vValue ); + CoTaskMemFree( recordset->prop[i].rgProperties ); + } + CoTaskMemFree( recordset->prop ); + recordset->prop_count = 0; + recordset->prop = NULL; }
static ULONG WINAPI recordset_Release( _Recordset *iface ) @@ -2382,6 +2395,10 @@ static HRESULT WINAPI recordset_Open( _Recordset *iface, VARIANT source, VARIANT return hr; }
+ _Recordset_put_CursorType( iface, cursor_type ); + if (lock_type < adLockReadOnly) lock_type = adLockReadOnly; + _Recordset_put_LockType( iface, lock_type ); + if (recordset->fields.count != -1) { DBCOLUMNINFO *info; @@ -2456,7 +2473,6 @@ static HRESULT WINAPI recordset_Open( _Recordset *iface, VARIANT source, VARIANT
hr = ADORecordsetConstruction_put_Rowset(&recordset->ADORecordsetConstruction_iface, rowset); IUnknown_Release(rowset); - recordset->cursor_type = cursor_type; return hr; }
@@ -3071,11 +3087,51 @@ static void init_bookmark( struct recordset *recordset ) CoTaskMemFree( colinfo ); }
+static BOOL recordset_get_prop( struct recordset *recordset, + const GUID *prop_set, DWORD propid, VARIANT *v ) +{ + HRESULT hr = E_FAIL; + int i, j; + + for (i = 0; i < recordset->prop_count; i++) + { + if (!IsEqualGUID( &recordset->prop[i].guidPropertySet, prop_set )) continue; + + for (j=0; j < recordset->prop[i].cProperties; j++) + { + if (recordset->prop[i].rgProperties[j].dwStatus == DBPROPSTATUS_OK && + recordset->prop[i].rgProperties[j].dwPropertyID == propid) + { + *v = recordset->prop[i].rgProperties[j].vValue; + break; + } + } + if (j != recordset->prop[i].cProperties) break; + } + if (i == recordset->prop_count) return FALSE; + + if (IsEqualGUID( prop_set, &DBPROPSET_ROWSET )) + { + switch (propid) + { + case DBPROP_UPDATABILITY: + hr = VariantChangeType( v, v, 0, VT_I4 ); + break; + case DBPROP_IRowsetUpdate: + hr = VariantChangeType( v, v, 0, VT_BOOL ); + break; + } + } + return SUCCEEDED( hr ); +} + static HRESULT WINAPI rsconstruction_put_Rowset(ADORecordsetConstruction *iface, IUnknown *unk) { struct recordset *recordset = impl_from_ADORecordsetConstruction( iface ); + IRowsetInfo *rowset_info; IRowset *rowset; HRESULT hr; + VARIANT v;
TRACE( "%p, %p\n", recordset, unk );
@@ -3086,6 +3142,32 @@ static HRESULT WINAPI rsconstruction_put_Rowset(ADORecordsetConstruction *iface, recordset->row_set = rowset; recordset->state = adStateOpen;
+ hr = IRowset_QueryInterface( rowset, &IID_IRowsetInfo, (void**)&rowset_info ); + if (SUCCEEDED(hr)) + { + DBPROPIDSET propidset; + DBPROPID propid[2]; + + propidset.guidPropertySet = DBPROPSET_ROWSET; + propidset.cPropertyIDs = 2; + propidset.rgPropertyIDs = propid; + propid[0] = DBPROP_UPDATABILITY; + propid[1] = DBPROP_IRowsetUpdate; + hr = IRowsetInfo_GetProperties( rowset_info, 1, &propidset, + &recordset->prop_count, &recordset->prop); + IRowsetInfo_Release( rowset_info ); + } + + if (recordset_get_prop( recordset, &DBPROPSET_ROWSET, DBPROP_UPDATABILITY, &v ) && V_I4( &v )) + { + if (recordset->lock_type != adLockOptimistic) + { + if (recordset_get_prop( recordset, &DBPROPSET_ROWSET, DBPROP_IRowsetUpdate, &v ) && V_BOOL( &v )) + recordset->lock_type = adLockBatchOptimistic; + } + } + else recordset->lock_type = adLockReadOnly; + hr = IRowset_QueryInterface( rowset, &IID_IRowsetLocate, (void**)&recordset->rowset_locate ); if (SUCCEEDED(hr)) init_bookmark( recordset ); return S_OK; diff --git a/dlls/msado15/tests/msado15.c b/dlls/msado15/tests/msado15.c index d7de54efd7e..3754e32b823 100644 --- a/dlls/msado15/tests/msado15.c +++ b/dlls/msado15/tests/msado15.c @@ -120,6 +120,7 @@ static void test_Recordset(void) BSTR name; HRESULT hr; VARIANT bookmark, filter, active; + LockTypeEnum lock_type; EditModeEnum editmode; IUnknown *rowset; LONG cache_size; @@ -241,19 +242,34 @@ static void test_Recordset(void) hr = _Recordset_AddNew( recordset, missing, missing ); ok( hr == MAKE_ADO_HRESULT( adErrObjectClosed ), "got %08lx\n", hr );
+ hr = _Recordset_get_LockType( recordset, &lock_type ); + ok( hr == S_OK, "got %08lx\n", hr ); + ok( lock_type == adLockReadOnly, "lock_type = %d\n", lock_type ); + + hr = _Recordset_put_LockType( recordset, adLockUnspecified ); + ok( hr == MAKE_ADO_HRESULT( adErrInvalidArgument ), "got %08lx\n", hr ); + V_VT( &missing ) = VT_ERROR; V_ERROR( &missing ) = DISP_E_PARAMNOTFOUND; hr = _Recordset_Open( recordset, missing, missing, adOpenStatic, adLockBatchOptimistic, adCmdUnspecified ); ok( hr == MAKE_ADO_HRESULT( adErrInvalidConnection ), "got %08lx\n", hr );
+ hr = _Recordset_get_LockType( recordset, &lock_type ); + ok( hr == S_OK, "got %08lx\n", hr ); + ok( lock_type == adLockBatchOptimistic, "lock_type = %d\n", lock_type ); + hr = _Recordset_get_Fields( recordset, &fields ); ok( hr == S_OK, "got %08lx\n", hr );
V_VT( &missing ) = VT_ERROR; V_ERROR( &missing ) = DISP_E_PARAMNOTFOUND; - hr = _Recordset_Open( recordset, missing, missing, adOpenStatic, adLockBatchOptimistic, adCmdUnspecified ); + hr = _Recordset_Open( recordset, missing, missing, adOpenStatic, adLockPessimistic, adCmdUnspecified ); ok( hr == MAKE_ADO_HRESULT( adErrInvalidConnection ), "got %08lx\n", hr );
+ hr = _Recordset_get_LockType( recordset, &lock_type ); + ok( hr == S_OK, "got %08lx\n", hr ); + ok( lock_type == adLockPessimistic, "lock_type = %d\n", lock_type ); + name = SysAllocString( L"field" ); hr = Fields__Append( fields, name, adInteger, 4, adFldUnspecified ); ok( hr == S_OK, "got %08lx\n", hr ); @@ -328,6 +344,10 @@ static void test_Recordset(void) ok( is_eof( recordset ), "not eof\n" ); ok( is_bof( recordset ), "not bof\n" );
+ hr = _Recordset_get_LockType( recordset, &lock_type ); + ok( hr == S_OK, "got %08lx\n", hr ); + ok( lock_type == adLockBatchOptimistic, "lock_type = %d\n", lock_type ); + hr = ADORecordsetConstruction_get_Rowset(recordset_constr, &rowset); ok(hr == S_OK, "failed %08lx\n", hr); ok(!!rowset, "rowset = NULL\n"); @@ -510,6 +530,10 @@ static void test_Recordset(void) hr = _Recordset_Close( recordset ); ok( hr == S_OK, "got %08lx\n", hr );
+ hr = _Recordset_get_LockType( recordset, &lock_type ); + ok( hr == S_OK, "got %08lx\n", hr ); + ok( lock_type == adLockBatchOptimistic, "lock_type = %d\n", lock_type ); + count = -1; hr = Fields_get_Count( fields, &count ); ok( !count, "got %ld\n", count ); @@ -1583,6 +1607,7 @@ static void test_ADORecordsetConstruction(BOOL exact_scroll) LONG count, state; unsigned char prec, scale; VARIANT index, missing, v; + LockTypeEnum lock_type; ADO_LONGPTR size; DataTypeEnum type;
@@ -1616,6 +1641,10 @@ static void test_ADORecordsetConstruction(BOOL exact_scroll)
rowset = (IUnknown*)&testrowset.IRowsetExactScroll_iface;
+ hr = _Recordset_get_LockType( recordset, &lock_type ); + ok( hr == S_OK, "got %08lx\n", hr ); + ok( lock_type == adLockReadOnly, "lock_type = %d\n", lock_type ); + SET_EXPECT( rowset_info_GetProperties ); SET_EXPECT( rowset_QI_IRowsetFind ); if (exact_scroll) @@ -1625,7 +1654,7 @@ static void test_ADORecordsetConstruction(BOOL exact_scroll) } SET_EXPECT( rowset_QI_IDBAsynchStatus ); hr = ADORecordsetConstruction_put_Rowset( construct, rowset ); - todo_wine CHECK_CALLED( rowset_info_GetProperties ); + CHECK_CALLED( rowset_info_GetProperties ); todo_wine CHECK_CALLED( rowset_QI_IRowsetFind ); if (exact_scroll) { @@ -1639,6 +1668,10 @@ static void test_ADORecordsetConstruction(BOOL exact_scroll) ok( hr == S_OK, "got %08lx\n", hr ); ok( state == adStateOpen, "state = %ld\n", state );
+ hr = _Recordset_get_LockType( recordset, &lock_type ); + ok( hr == S_OK, "got %08lx\n", hr ); + ok( lock_type == adLockBatchOptimistic, "lock_type = %d\n", lock_type ); + count = -1; SET_EXPECT( column_info_GetColumnInfo ); hr = Fields_get_Count( fields, &count );