From 0988938d0fd692e6de2856222f947b75f460d830 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Mon, 26 Aug 2013 08:47:28 +0400 Subject: [PATCH] oledb32: Implement SetRowPosition(). --- dlls/oledb32/rowpos.c | 66 ++++++++++++++++++++++++++++++++--- dlls/oledb32/tests/database.c | 36 ++++++++++++++----- 2 files changed, 90 insertions(+), 12 deletions(-) diff --git a/dlls/oledb32/rowpos.c b/dlls/oledb32/rowpos.c index 2b932c91591..c1cee127e84 100644 --- a/dlls/oledb32/rowpos.c +++ b/dlls/oledb32/rowpos.c @@ -47,9 +47,11 @@ struct rowpos LONG ref; IRowset *rowset; + IChapteredRowset *chrst; HROW row; HCHAPTER chapter; DBPOSITIONFLAGS flags; + BOOL cleared; rowpos_cp cp; }; @@ -72,13 +74,14 @@ static inline rowpos_cp *impl_from_IConnectionPoint(IConnectionPoint *iface) static HRESULT rowpos_fireevent(rowpos *rp, DBREASON reason, DBEVENTPHASE phase) { + BOOL cant_deny = phase == DBEVENTPHASE_FAILEDTODO || phase == DBEVENTPHASE_SYNCHAFTER; HRESULT hr = S_OK; DWORD i; for (i = 0; i < rp->cp.sinks_size; i++) if (rp->cp.sinks[i]) { - hr = IRowPositionChange_OnRowPositionChange(rp->cp.sinks[i], reason, phase, phase == DBEVENTPHASE_FAILEDTODO); + hr = IRowPositionChange_OnRowPositionChange(rp->cp.sinks[i], reason, phase, cant_deny); if (phase == DBEVENTPHASE_FAILEDTODO) return DB_E_CANCELED; if (hr != S_OK) return hr; } @@ -88,6 +91,14 @@ static HRESULT rowpos_fireevent(rowpos *rp, DBREASON reason, DBEVENTPHASE phase) static void rowpos_clearposition(rowpos *rp) { + if (!rp->cleared) + { + if (rp->rowset) + IRowset_ReleaseRows(rp->rowset, 1, &rp->row, NULL, NULL, NULL); + if (rp->chrst) + IChapteredRowset_ReleaseChapter(rp->chrst, rp->chapter, NULL); + } + rp->row = DB_NULL_HROW; rp->chapter = DB_NULL_HCHAPTER; rp->flags = DBPOSITION_NOROW; @@ -138,6 +149,7 @@ static ULONG WINAPI rowpos_Release(IRowPosition* iface) if (ref == 0) { if (This->rowset) IRowset_Release(This->rowset); + if (This->chrst) IChapteredRowset_Release(This->chrst); rowposchange_cp_destroy(&This->cp); heap_free(This); } @@ -163,6 +175,7 @@ static HRESULT WINAPI rowpos_ClearRowPosition(IRowPosition* iface) return rowpos_fireevent(This, DBREASON_ROWPOSITION_CLEARED, DBEVENTPHASE_FAILEDTODO); rowpos_clearposition(This); + This->cleared = TRUE; return S_OK; } @@ -195,20 +208,63 @@ static HRESULT WINAPI rowpos_GetRowset(IRowPosition *iface, REFIID riid, IUnknow static HRESULT WINAPI rowpos_Initialize(IRowPosition *iface, IUnknown *rowset) { rowpos *This = impl_from_IRowPosition(iface); + HRESULT hr; TRACE("(%p)->(%p)\n", This, rowset); if (This->rowset) return DB_E_ALREADYINITIALIZED; - return IUnknown_QueryInterface(rowset, &IID_IRowset, (void**)&This->rowset); + hr = IUnknown_QueryInterface(rowset, &IID_IRowset, (void**)&This->rowset); + if (FAILED(hr)) return hr; + + /* this one is optional */ + IUnknown_QueryInterface(rowset, &IID_IChapteredRowset, (void**)&This->chrst); + return S_OK; } static HRESULT WINAPI rowpos_SetRowPosition(IRowPosition *iface, HCHAPTER chapter, HROW row, DBPOSITIONFLAGS flags) { rowpos *This = impl_from_IRowPosition(iface); - FIXME("(%p)->(%lx %lx %d): stub\n", This, chapter, row, flags); - return E_NOTIMPL; + DBREASON reason; + HRESULT hr; + + TRACE("(%p)->(%lx %lx %d)\n", This, chapter, row, flags); + + if (!This->cleared) return E_UNEXPECTED; + + hr = IRowset_AddRefRows(This->rowset, 1, &row, NULL, NULL); + if (FAILED(hr)) return hr; + + if (This->chrst) + { + hr = IChapteredRowset_AddRefChapter(This->chrst, chapter, NULL); + if (FAILED(hr)) + { + IRowset_ReleaseRows(This->rowset, 1, &row, NULL, NULL, NULL); + return hr; + } + } + + reason = This->chrst ? DBREASON_ROWPOSITION_CHAPTERCHANGED : DBREASON_ROWPOSITION_CHANGED; + hr = rowpos_fireevent(This, reason, DBEVENTPHASE_SYNCHAFTER); + if (hr != S_OK) + { + IRowset_ReleaseRows(This->rowset, 1, &row, NULL, NULL, NULL); + if (This->chrst) + IChapteredRowset_ReleaseChapter(This->chrst, chapter, NULL); + return rowpos_fireevent(This, reason, DBEVENTPHASE_FAILEDTODO); + } + else + rowpos_fireevent(This, reason, DBEVENTPHASE_DIDEVENT); + + /* previously set chapter and row are released with ClearRowPosition() */ + This->chapter = chapter; + This->row = row; + This->flags = flags; + This->cleared = FALSE; + + return S_OK; } static const struct IRowPositionVtbl rowpos_vtbl = @@ -434,6 +490,8 @@ HRESULT create_oledb_rowpos(IUnknown *outer, void **obj) This->IConnectionPointContainer_iface.lpVtbl = &rowpos_cpc_vtbl; This->ref = 1; This->rowset = NULL; + This->chrst = NULL; + This->cleared = FALSE; rowpos_clearposition(This); rowposchange_cp_init(&This->cp, This); diff --git a/dlls/oledb32/tests/database.c b/dlls/oledb32/tests/database.c index 7801bf84773..d0eb9ff3078 100644 --- a/dlls/oledb32/tests/database.c +++ b/dlls/oledb32/tests/database.c @@ -317,8 +317,8 @@ static ULONG WINAPI rset_Release(IRowset *iface) static HRESULT WINAPI rset_AddRefRows(IRowset *iface, DBCOUNTITEM cRows, const HROW rghRows[], DBREFCOUNT rgRefCounts[], DBROWSTATUS rgRowStatus[]) { - ok(0, "unexpected call\n"); - return E_NOTIMPL; + trace("AddRefRows: %ld\n", rghRows[0]); + return S_OK; } static HRESULT WINAPI rset_GetData(IRowset *iface, HROW hRow, HACCESSOR hAccessor, void *pData) @@ -337,8 +337,7 @@ static HRESULT WINAPI rset_GetNextRows(IRowset *iface, HCHAPTER hReserved, DBROW static HRESULT WINAPI rset_ReleaseRows(IRowset *iface, DBCOUNTITEM cRows, const HROW rghRows[], DBROWOPTIONS rgRowOptions[], DBREFCOUNT rgRefCounts[], DBROWSTATUS rgRowStatus[]) { - ok(0, "unexpected call\n"); - return E_NOTIMPL; + return S_OK; } static HRESULT WINAPI rset_RestartPosition(IRowset *iface, HCHAPTER hReserved) @@ -375,14 +374,12 @@ static ULONG WINAPI chrset_Release(IChapteredRowset *iface) static HRESULT WINAPI chrset_AddRefChapter(IChapteredRowset *iface, HCHAPTER chapter, DBREFCOUNT *refcount) { - ok(0, "unexpected call\n"); - return E_NOTIMPL; + return S_OK; } static HRESULT WINAPI chrset_ReleaseChapter(IChapteredRowset *iface, HCHAPTER chapter, DBREFCOUNT *refcount) { - ok(0, "unexpected call\n"); - return E_NOTIMPL; + return S_OK; } static const IChapteredRowsetVtbl chrset_vtbl = { @@ -528,6 +525,28 @@ static void test_rowpos_clearrowposition(void) IRowPosition_Release(rowpos); } +static void test_rowpos_setrowposition(void) +{ + IRowPosition *rowpos; + HRESULT hr; + + hr = CoCreateInstance(&CLSID_OLEDB_ROWPOSITIONLIBRARY, NULL, CLSCTX_INPROC_SERVER, &IID_IRowPosition, (void**)&rowpos); + ok(hr == S_OK, "got %08x\n", hr); + + init_test_rset(); + hr = IRowPosition_Initialize(rowpos, (IUnknown*)&test_rset.IRowset_iface); + ok(hr == S_OK, "got %08x\n", hr); + + hr = IRowPosition_ClearRowPosition(rowpos); + ok(hr == S_OK, "got %08x\n", hr); + + init_onchange_sink(rowpos); + hr = IRowPosition_SetRowPosition(rowpos, 0x123, 0x456, DBPOSITION_OK); + ok(hr == S_OK, "got %08x\n", hr); + + IRowPosition_Release(rowpos); +} + START_TEST(database) { OleInitialize(NULL); @@ -540,6 +559,7 @@ START_TEST(database) test_rowposition(); test_rowpos_initialize(); test_rowpos_clearrowposition(); + test_rowpos_setrowposition(); OleUninitialize(); }