oledb32: Implement SetRowPosition().

This commit is contained in:
Nikolay Sivov 2013-08-26 08:47:28 +04:00 committed by Alexandre Julliard
parent 4d565644b6
commit 0988938d0f
2 changed files with 90 additions and 12 deletions

View File

@ -47,9 +47,11 @@ struct rowpos
LONG ref; LONG ref;
IRowset *rowset; IRowset *rowset;
IChapteredRowset *chrst;
HROW row; HROW row;
HCHAPTER chapter; HCHAPTER chapter;
DBPOSITIONFLAGS flags; DBPOSITIONFLAGS flags;
BOOL cleared;
rowpos_cp cp; 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) static HRESULT rowpos_fireevent(rowpos *rp, DBREASON reason, DBEVENTPHASE phase)
{ {
BOOL cant_deny = phase == DBEVENTPHASE_FAILEDTODO || phase == DBEVENTPHASE_SYNCHAFTER;
HRESULT hr = S_OK; HRESULT hr = S_OK;
DWORD i; DWORD i;
for (i = 0; i < rp->cp.sinks_size; i++) for (i = 0; i < rp->cp.sinks_size; i++)
if (rp->cp.sinks[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 (phase == DBEVENTPHASE_FAILEDTODO) return DB_E_CANCELED;
if (hr != S_OK) return hr; 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) 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->row = DB_NULL_HROW;
rp->chapter = DB_NULL_HCHAPTER; rp->chapter = DB_NULL_HCHAPTER;
rp->flags = DBPOSITION_NOROW; rp->flags = DBPOSITION_NOROW;
@ -138,6 +149,7 @@ static ULONG WINAPI rowpos_Release(IRowPosition* iface)
if (ref == 0) if (ref == 0)
{ {
if (This->rowset) IRowset_Release(This->rowset); if (This->rowset) IRowset_Release(This->rowset);
if (This->chrst) IChapteredRowset_Release(This->chrst);
rowposchange_cp_destroy(&This->cp); rowposchange_cp_destroy(&This->cp);
heap_free(This); heap_free(This);
} }
@ -163,6 +175,7 @@ static HRESULT WINAPI rowpos_ClearRowPosition(IRowPosition* iface)
return rowpos_fireevent(This, DBREASON_ROWPOSITION_CLEARED, DBEVENTPHASE_FAILEDTODO); return rowpos_fireevent(This, DBREASON_ROWPOSITION_CLEARED, DBEVENTPHASE_FAILEDTODO);
rowpos_clearposition(This); rowpos_clearposition(This);
This->cleared = TRUE;
return S_OK; 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) static HRESULT WINAPI rowpos_Initialize(IRowPosition *iface, IUnknown *rowset)
{ {
rowpos *This = impl_from_IRowPosition(iface); rowpos *This = impl_from_IRowPosition(iface);
HRESULT hr;
TRACE("(%p)->(%p)\n", This, rowset); TRACE("(%p)->(%p)\n", This, rowset);
if (This->rowset) return DB_E_ALREADYINITIALIZED; 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, static HRESULT WINAPI rowpos_SetRowPosition(IRowPosition *iface, HCHAPTER chapter,
HROW row, DBPOSITIONFLAGS flags) HROW row, DBPOSITIONFLAGS flags)
{ {
rowpos *This = impl_from_IRowPosition(iface); rowpos *This = impl_from_IRowPosition(iface);
FIXME("(%p)->(%lx %lx %d): stub\n", This, chapter, row, flags); DBREASON reason;
return E_NOTIMPL; 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 = 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->IConnectionPointContainer_iface.lpVtbl = &rowpos_cpc_vtbl;
This->ref = 1; This->ref = 1;
This->rowset = NULL; This->rowset = NULL;
This->chrst = NULL;
This->cleared = FALSE;
rowpos_clearposition(This); rowpos_clearposition(This);
rowposchange_cp_init(&This->cp, This); rowposchange_cp_init(&This->cp, This);

View File

@ -317,8 +317,8 @@ static ULONG WINAPI rset_Release(IRowset *iface)
static HRESULT WINAPI rset_AddRefRows(IRowset *iface, DBCOUNTITEM cRows, static HRESULT WINAPI rset_AddRefRows(IRowset *iface, DBCOUNTITEM cRows,
const HROW rghRows[], DBREFCOUNT rgRefCounts[], DBROWSTATUS rgRowStatus[]) const HROW rghRows[], DBREFCOUNT rgRefCounts[], DBROWSTATUS rgRowStatus[])
{ {
ok(0, "unexpected call\n"); trace("AddRefRows: %ld\n", rghRows[0]);
return E_NOTIMPL; return S_OK;
} }
static HRESULT WINAPI rset_GetData(IRowset *iface, HROW hRow, HACCESSOR hAccessor, void *pData) 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[], static HRESULT WINAPI rset_ReleaseRows(IRowset *iface, DBCOUNTITEM cRows, const HROW rghRows[], DBROWOPTIONS rgRowOptions[],
DBREFCOUNT rgRefCounts[], DBROWSTATUS rgRowStatus[]) DBREFCOUNT rgRefCounts[], DBROWSTATUS rgRowStatus[])
{ {
ok(0, "unexpected call\n"); return S_OK;
return E_NOTIMPL;
} }
static HRESULT WINAPI rset_RestartPosition(IRowset *iface, HCHAPTER hReserved) 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) static HRESULT WINAPI chrset_AddRefChapter(IChapteredRowset *iface, HCHAPTER chapter, DBREFCOUNT *refcount)
{ {
ok(0, "unexpected call\n"); return S_OK;
return E_NOTIMPL;
} }
static HRESULT WINAPI chrset_ReleaseChapter(IChapteredRowset *iface, HCHAPTER chapter, DBREFCOUNT *refcount) static HRESULT WINAPI chrset_ReleaseChapter(IChapteredRowset *iface, HCHAPTER chapter, DBREFCOUNT *refcount)
{ {
ok(0, "unexpected call\n"); return S_OK;
return E_NOTIMPL;
} }
static const IChapteredRowsetVtbl chrset_vtbl = { static const IChapteredRowsetVtbl chrset_vtbl = {
@ -528,6 +525,28 @@ static void test_rowpos_clearrowposition(void)
IRowPosition_Release(rowpos); 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) START_TEST(database)
{ {
OleInitialize(NULL); OleInitialize(NULL);
@ -540,6 +559,7 @@ START_TEST(database)
test_rowposition(); test_rowposition();
test_rowpos_initialize(); test_rowpos_initialize();
test_rowpos_clearrowposition(); test_rowpos_clearrowposition();
test_rowpos_setrowposition();
OleUninitialize(); OleUninitialize();
} }