diff --git a/dlls/oledb32/rowpos.c b/dlls/oledb32/rowpos.c index d322a9db1dc..a6c68b8ef07 100644 --- a/dlls/oledb32/rowpos.c +++ b/dlls/oledb32/rowpos.c @@ -67,6 +67,22 @@ static inline rowpos_cp *impl_from_IConnectionPoint(IConnectionPoint *iface) return CONTAINING_RECORD(iface, rowpos_cp, IConnectionPoint_iface); } +static HRESULT rowpos_fireevent(rowpos *rp, DBREASON reason, DBEVENTPHASE phase) +{ + 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); + if (phase == DBEVENTPHASE_FAILEDTODO) return DB_E_CANCELED; + if (hr != S_OK) return hr; + } + + return hr; +} + static HRESULT WINAPI rowpos_QueryInterface(IRowPosition* iface, REFIID riid, void **obj) { rowpos *This = impl_from_IRowPosition(iface); @@ -122,8 +138,23 @@ static ULONG WINAPI rowpos_Release(IRowPosition* iface) static HRESULT WINAPI rowpos_ClearRowPosition(IRowPosition* iface) { rowpos *This = impl_from_IRowPosition(iface); - FIXME("(%p): stub\n", This); - return E_NOTIMPL; + HRESULT hr; + + TRACE("(%p)\n", This); + + if (!This->rowset) return E_UNEXPECTED; + + hr = rowpos_fireevent(This, DBREASON_ROWPOSITION_CLEARED, DBEVENTPHASE_OKTODO); + if (hr != S_OK) + return rowpos_fireevent(This, DBREASON_ROWPOSITION_CLEARED, DBEVENTPHASE_FAILEDTODO); + + hr = rowpos_fireevent(This, DBREASON_ROWPOSITION_CLEARED, DBEVENTPHASE_ABOUTTODO); + if (hr != S_OK) + return rowpos_fireevent(This, DBREASON_ROWPOSITION_CLEARED, DBEVENTPHASE_FAILEDTODO); + + /* FIXME: actually clear stored data */ + + return S_OK; } static HRESULT WINAPI rowpos_GetRowPosition(IRowPosition *iface, HCHAPTER *chapter, @@ -277,6 +308,8 @@ static HRESULT WINAPI rowpos_cp_Advise(IConnectionPoint *iface, IUnknown *unksin TRACE("(%p)->(%p %p)\n", This, unksink, cookie); + if (!cookie) return E_POINTER; + hr = IUnknown_QueryInterface(unksink, &IID_IRowPositionChange, (void**)&sink); if (FAILED(hr)) { diff --git a/dlls/oledb32/tests/database.c b/dlls/oledb32/tests/database.c index 585196cf55f..f42f189e3ef 100644 --- a/dlls/oledb32/tests/database.c +++ b/dlls/oledb32/tests/database.c @@ -414,6 +414,83 @@ static void test_rowpos_initialize(void) IRowPosition_Release(rowpos); } +static HRESULT WINAPI onchange_QI(IRowPositionChange *iface, REFIID riid, void **obj) +{ + if (IsEqualIID(riid, &IID_IUnknown) || + IsEqualIID(riid, &IID_IRowPositionChange)) + { + *obj = iface; + return S_OK; + } + + return E_NOINTERFACE; +} + +static ULONG WINAPI onchange_AddRef(IRowPositionChange *iface) +{ + return 2; +} + +static ULONG WINAPI onchange_Release(IRowPositionChange *iface) +{ + return 1; +} + +static HRESULT WINAPI onchange_OnRowPositionChange(IRowPositionChange *iface, DBREASON reason, + DBEVENTPHASE phase, BOOL cant_deny) +{ + trace("%d %d %d\n", reason, phase, cant_deny); + return S_OK; +} + +static const IRowPositionChangeVtbl onchange_vtbl = { + onchange_QI, + onchange_AddRef, + onchange_Release, + onchange_OnRowPositionChange +}; + +static IRowPositionChange onchangesink = { &onchange_vtbl }; + +static void init_onchange_sink(IRowPosition *rowpos) +{ + IConnectionPointContainer *cpc; + IConnectionPoint *cp; + DWORD cookie; + HRESULT hr; + + hr = IRowPosition_QueryInterface(rowpos, &IID_IConnectionPointContainer, (void**)&cpc); + ok(hr == S_OK, "got %08x\n", hr); + hr = IConnectionPointContainer_FindConnectionPoint(cpc, &IID_IRowPositionChange, &cp); + ok(hr == S_OK, "got %08x\n", hr); + hr = IConnectionPoint_Advise(cp, (IUnknown*)&onchangesink, &cookie); + ok(hr == S_OK, "got %08x\n", hr); + IConnectionPoint_Release(cp); + IConnectionPointContainer_Release(cpc); +} + +static void test_rowpos_clearrowposition(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); + + hr = IRowPosition_ClearRowPosition(rowpos); + ok(hr == E_UNEXPECTED, "got %08x\n", hr); + + init_test_rset(); + hr = IRowPosition_Initialize(rowpos, (IUnknown*)&test_rset.IRowset_iface); + ok(hr == S_OK, "got %08x\n", hr); + + init_onchange_sink(rowpos); + hr = IRowPosition_ClearRowPosition(rowpos); + ok(hr == S_OK, "got %08x\n", hr); + + IRowPosition_Release(rowpos); +} + START_TEST(database) { OleInitialize(NULL); @@ -425,6 +502,7 @@ START_TEST(database) /* row position */ test_rowposition(); test_rowpos_initialize(); + test_rowpos_clearrowposition(); OleUninitialize(); } diff --git a/include/dbs.idl b/include/dbs.idl index 46deb6ac526..ceb9773bae2 100644 --- a/include/dbs.idl +++ b/include/dbs.idl @@ -686,3 +686,39 @@ typedef struct tagDBTIMESTAMP { USHORT second; ULONG fraction; } DBTIMESTAMP; + +typedef DWORD DBREASON; +typedef DWORD DBEVENTPHASE; + +enum DBEVENTPHASEENUM { + DBEVENTPHASE_OKTODO, + DBEVENTPHASE_ABOUTTODO, + DBEVENTPHASE_SYNCHAFTER, + DBEVENTPHASE_FAILEDTODO, + DBEVENTPHASE_DIDEVENT +}; + +enum DBREASONENUM { + DBREASON_ROWSET_FETCHPOSITIONCHANGE, + DBREASON_ROWSET_RELEASE, + DBREASON_COLUMN_SET, + DBREASON_COLUMN_RECALCULATED, + DBREASON_ROW_ACTIVATE, + DBREASON_ROW_RELEASE, + DBREASON_ROW_DELETE, + DBREASON_ROW_FIRSTCHANCE, + DBREASON_ROW_INSERT, + DBREASON_ROW_RESYNCH, + DBREASON_ROW_UNDOCHANGE, + DBREASON_ROW_UNDOINSERT, + DBREASON_ROW_UNDODELETE, + DBREASON_ROW_UPDATE, + DBREASON_ROWSET_CHANGED +}; + +enum DBREASONENUM15 { + DBREASON_ROWPOSITION_CHANGED = DBREASON_ROWSET_CHANGED + 1, + DBREASON_ROWPOSITION_CHAPTERCHANGED, + DBREASON_ROWPOSITION_CLEARED, + DBREASON_ROW_ASYNCHINSERT +}; diff --git a/include/oledb.idl b/include/oledb.idl index 34cbd349720..8d7f001ac26 100644 --- a/include/oledb.idl +++ b/include/oledb.idl @@ -34,8 +34,6 @@ typedef LONG_PTR DBROWCOUNT; typedef ULONG_PTR DBCOUNTITEM; typedef ULONG_PTR DBLENGTH; typedef ULONG_PTR DBORDINAL; -typedef DWORD DBREASON; -typedef DWORD DBEVENTPHASE; typedef ULONG_PTR DBBKMARK; typedef DWORD_PTR DB_DWRESERVE; typedef ULONG_PTR DBREFCOUNT; diff --git a/include/oledberr.h b/include/oledberr.h index c739d237871..96adcae53fc 100644 --- a/include/oledberr.h +++ b/include/oledberr.h @@ -63,6 +63,7 @@ #define DB_E_BADACCESSORTYPE 0x80040e4b #define DB_E_WRITEONLYACCESSOR 0x80040e4c #define DB_SEC_E_AUTH_FAILED 0x80040e4d +#define DB_E_CANCELED 0x80040e4e #define DB_E_ALREADYINITIALIZED 0x80040e52 #define DB_E_DATAOVERFLOW 0x80040e57