Nikolay Sivov : oledb32: Implement SetRowPosition().

Alexandre Julliard julliard at winehq.org
Mon Aug 26 13:21:57 CDT 2013


Module: wine
Branch: master
Commit: 0988938d0fd692e6de2856222f947b75f460d830
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=0988938d0fd692e6de2856222f947b75f460d830

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Mon Aug 26 08:47:28 2013 +0400

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 2b932c9..c1cee12 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 7801bf8..d0eb9ff 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();
 }




More information about the wine-cvs mailing list