From: Piotr Caban <piotr(a)codeweavers.com> --- dlls/msado15/recordset.c | 38 ++++++++++++++++++++++++++++-- dlls/msado15/tests/msado15.c | 45 ++++++++++++++++++++++++++++++------ 2 files changed, 74 insertions(+), 9 deletions(-) diff --git a/dlls/msado15/recordset.c b/dlls/msado15/recordset.c index 300ed759f75..5ae4dbcb7fd 100644 --- a/dlls/msado15/recordset.c +++ b/dlls/msado15/recordset.c @@ -98,6 +98,7 @@ struct recordset IRowsetLocate *rowset_locate; IRowsetExactScroll *rowset_es; IRowsetChange *rowset_change; + IRowsetUpdate *rowset_update; IAccessor *accessor; IRowsetCurrentIndex *rowset_cur_idx; EditModeEnum editmode; @@ -1641,6 +1642,9 @@ static void close_recordset( struct recordset *recordset ) if ( recordset->rowset_change && recordset->rowset_change != NO_INTERFACE ) IRowsetChange_Release( recordset->rowset_change ); recordset->rowset_change = NULL; + if ( recordset->rowset_update && recordset->rowset_update != NO_INTERFACE ) + IRowsetUpdate_Release( recordset->rowset_update ); + recordset->rowset_update = NULL; if ( recordset->rowset_cur_idx && recordset->rowset_cur_idx != NO_INTERFACE ) IRowsetCurrentIndex_Release( recordset->rowset_cur_idx ); recordset->rowset_cur_idx = NULL; @@ -2196,12 +2200,42 @@ static HRESULT WINAPI recordset_AddNew( _Recordset *iface, VARIANT field_list, V static HRESULT WINAPI recordset_CancelUpdate( _Recordset *iface ) { struct recordset *recordset = impl_from_Recordset( iface ); + DBPENDINGSTATUS pending_status; + DBROWSTATUS *status; + DBCOUNTITEM count; + HRESULT hr; + HROW *row; - FIXME( "%p\n", iface ); + TRACE( "%p\n", iface ); - if (recordset->active_connection == NULL) + if (recordset->state == adStateClosed) return MAKE_ADO_HRESULT( adErrObjectClosed ); + if (!recordset->current_row) return MAKE_ADO_HRESULT( adErrNoCurrentRecord ); + + if (!recordset->rowset_update) + { + hr = IRowset_QueryInterface( recordset->row_set, &IID_IRowsetUpdate, + (void **)&recordset->rowset_update ); + if (FAILED(hr) || !recordset->rowset_update) + recordset->rowset_update = NO_INTERFACE; + } + if (recordset->rowset_update == NO_INTERFACE) return S_OK; + + hr = IRowsetUpdate_GetRowStatus( recordset->rowset_update, 0, + 1, &recordset->current_row, &pending_status ); + if (FAILED(hr)) return S_OK; + if (pending_status & (DBPENDINGSTATUS_UNCHANGED | DBPENDINGSTATUS_INVALIDROW)) return S_OK; + if (!(pending_status & (DBPENDINGSTATUS_NEW | DBPENDINGSTATUS_CHANGED | DBPENDINGSTATUS_DELETED))) return S_OK; + row = NULL; + status = NULL; + hr = IRowsetUpdate_Undo( recordset->rowset_update, 0, 1, &recordset->current_row, &count, &row, &status ); + if (FAILED(hr)) return hr; + if (status[0] == DBROWSTATUS_E_CANCELED) FIXME("status = DBROWSTATUS_E_CANCELED\n"); + if (pending_status & DBPENDINGSTATUS_NEW) cache_release( recordset ); + CoTaskMemFree( row ); + CoTaskMemFree( status ); + recordset->editmode = adEditNone; return S_OK; } diff --git a/dlls/msado15/tests/msado15.c b/dlls/msado15/tests/msado15.c index 02228237e1f..430970caf3d 100644 --- a/dlls/msado15/tests/msado15.c +++ b/dlls/msado15/tests/msado15.c @@ -80,6 +80,8 @@ DEFINE_EXPECT(rowset_GetData); DEFINE_EXPECT(rowset_RestartPosition); DEFINE_EXPECT(rowset_update_SetData); DEFINE_EXPECT(rowset_update_InsertRow); +DEFINE_EXPECT(rowset_update_GetRowStatus); +DEFINE_EXPECT(rowset_update_Undo); DEFINE_EXPECT(accessor_AddRefAccessor); DEFINE_EXPECT(accessor_CreateAccessor); DEFINE_EXPECT(accessor_ReleaseAccessor); @@ -957,15 +959,32 @@ static HRESULT WINAPI rowset_update_GetPendingRows(IRowsetUpdate *iface, static HRESULT WINAPI rowset_update_GetRowStatus(IRowsetUpdate *iface, HCHAPTER reserved, DBCOUNTITEM count, const HROW rows[], DBPENDINGSTATUS status[]) { - ok(0, "Unexpected call\n"); - return E_NOTIMPL; + CHECK_EXPECT(rowset_update_GetRowStatus); + ok(!reserved, "reserved = %Id\n", reserved); + ok(count == 1, "count = %Id\n", count); + ok(rows[0] == 10, "rows[0] = %Id\n", rows[0]); + + status[0] = DBPENDINGSTATUS_NEW; + return S_OK; } static HRESULT WINAPI rowset_update_Undo(IRowsetUpdate *iface, HCHAPTER reserved, DBCOUNTITEM count, const HROW rows[], DBCOUNTITEM *undone_cnt, HROW **undone, DBROWSTATUS **status) { - ok(0, "Unexpected call\n"); - return E_NOTIMPL; + CHECK_EXPECT(rowset_update_Undo); + ok(!reserved, "reserved = %Id\n", reserved); + ok(count == 1, "count = %Id\n", count); + ok(rows[0] == 10, "rows[0] = %Id\n", rows[0]); + ok(undone_cnt != NULL, "undone_cnt = NULL\n"); + ok(undone != NULL, "undone = NULL\n"); + ok(status != NULL, "status = NULL\n"); + + *undone_cnt = 1; + *undone = CoTaskMemAlloc(sizeof(**undone)); + *undone[0] = rows[0]; + *status = CoTaskMemAlloc(sizeof(**status)); + *status[0] = DBROWSTATUS_S_OK; + return S_OK; } static HRESULT WINAPI rowset_update_Update(IRowsetUpdate *iface, HCHAPTER reserved, DBCOUNTITEM count, @@ -2047,9 +2066,22 @@ static void test_ADORecordsetConstruction(BOOL exact_scroll) CHECK_CALLED(accessor_ReleaseAccessor); if (exact_scroll) CHECK_EXPECT(rowset_GetData); + SET_EXPECT(rowset_update_GetRowStatus); + SET_EXPECT(rowset_update_Undo); + SET_EXPECT(rowset_AddRefRows); + SET_EXPECT(rowset_ReleaseRows); + hr = _Recordset_CancelUpdate( recordset ); + ok( hr == S_OK, "got %08lx\n", hr ); + CHECK_CALLED(rowset_update_GetRowStatus); + CHECK_CALLED(rowset_update_Undo); + todo_wine CHECK_CALLED(rowset_AddRefRows); + CHECK_CALLED(rowset_ReleaseRows); + + hr = _Recordset_CancelUpdate( recordset ); + ok( hr == MAKE_ADO_HRESULT( adErrNoCurrentRecord ), "got %08lx\n", hr ); + V_VT(&v) = VT_BSTR; V_BSTR(&v) = SysAllocString( L"Column1 = 1" ); - SET_EXPECT(rowset_AddRefRows); SET_EXPECT(rowset_ReleaseRows); SET_EXPECT(accessor_CreateAccessor); SET_EXPECT(accessor_AddRefAccessor); @@ -2069,7 +2101,6 @@ static void test_ADORecordsetConstruction(BOOL exact_scroll) } hr = _Recordset_put_Filter( recordset, v ); todo_wine ok( hr == S_OK, "got %08lx\n", hr ); - todo_wine CHECK_CALLED(rowset_AddRefRows); todo_wine CHECK_CALLED(rowset_ReleaseRows); todo_wine CHECK_CALLED(accessor_CreateAccessor); todo_wine CHECK_CALLED(accessor_AddRefAccessor); @@ -2095,7 +2126,7 @@ static void test_ADORecordsetConstruction(BOOL exact_scroll) SET_EXPECT(accessor_ReleaseAccessor); SET_EXPECT(chaptered_rowset_ReleaseChapter); ok( !_Recordset_Release( recordset ), "_Recordset not released\n" ); - CHECK_CALLED(rowset_ReleaseRows ); + todo_wine CHECK_CALLED(rowset_ReleaseRows ); CHECK_CALLED(accessor_ReleaseAccessor); todo_wine CHECK_CALLED(chaptered_rowset_ReleaseChapter); ok( testrowset.refs == 1, "got %ld\n", testrowset.refs ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9678