From f339c2fa0d6e4df480e9e9a6507a831051f1f657 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Thu, 22 Aug 2013 14:33:31 +0400 Subject: [PATCH] oledb32: Implement Advise/Unadvise for IRowPositionChange. --- dlls/oledb32/oledb_private.h | 10 +++++ dlls/oledb32/rowpos.c | 72 +++++++++++++++++++++++++++++++++--- 2 files changed, 77 insertions(+), 5 deletions(-) diff --git a/dlls/oledb32/oledb_private.h b/dlls/oledb32/oledb_private.h index 15705294fc7..c23246463ae 100644 --- a/dlls/oledb32/oledb_private.h +++ b/dlls/oledb32/oledb_private.h @@ -27,6 +27,16 @@ static inline void *heap_alloc(size_t len) return HeapAlloc(GetProcessHeap(), 0, len); } +static inline void *heap_alloc_zero(size_t len) +{ + return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); +} + +static inline void *heap_realloc_zero(void *mem, size_t len) +{ + return HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, mem, len); +} + static inline BOOL heap_free(void *mem) { return HeapFree(GetProcessHeap(), 0, mem); diff --git a/dlls/oledb32/rowpos.c b/dlls/oledb32/rowpos.c index 3461842fa6c..d322a9db1dc 100644 --- a/dlls/oledb32/rowpos.c +++ b/dlls/oledb32/rowpos.c @@ -36,6 +36,8 @@ typedef struct { IConnectionPoint IConnectionPoint_iface; rowpos *container; + IRowPositionChange **sinks; + DWORD sinks_size; } rowpos_cp; struct rowpos @@ -48,6 +50,8 @@ struct rowpos rowpos_cp cp; }; +static void rowposchange_cp_destroy(rowpos_cp*); + static inline rowpos *impl_from_IRowPosition(IRowPosition *iface) { return CONTAINING_RECORD(iface, rowpos, IRowPosition_iface); @@ -108,6 +112,7 @@ static ULONG WINAPI rowpos_Release(IRowPosition* iface) if (ref == 0) { if (This->rowset) IRowset_Release(This->rowset); + rowposchange_cp_destroy(&This->cp); heap_free(This); } @@ -263,18 +268,62 @@ static HRESULT WINAPI rowpos_cp_GetConnectionPointContainer(IConnectionPoint *if return S_OK; } -static HRESULT WINAPI rowpos_cp_Advise(IConnectionPoint *iface, IUnknown *sink, DWORD *cookie) +static HRESULT WINAPI rowpos_cp_Advise(IConnectionPoint *iface, IUnknown *unksink, DWORD *cookie) { rowpos_cp *This = impl_from_IConnectionPoint(iface); - FIXME("(%p)->(%p %p): stub\n", This, sink, cookie); - return E_NOTIMPL; + IRowPositionChange *sink; + HRESULT hr; + DWORD i; + + TRACE("(%p)->(%p %p)\n", This, unksink, cookie); + + hr = IUnknown_QueryInterface(unksink, &IID_IRowPositionChange, (void**)&sink); + if (FAILED(hr)) + { + FIXME("sink doesn't support IRowPositionChange\n"); + return CONNECT_E_CANNOTCONNECT; + } + + if (This->sinks) + { + for (i = 0; i < This->sinks_size; i++) + { + if (!This->sinks[i]) + break; + } + + if (i == This->sinks_size) + { + This->sinks_size *= 2; + This->sinks = heap_realloc_zero(This->sinks, This->sinks_size*sizeof(*This->sinks)); + } + } + else + { + This->sinks_size = 10; + This->sinks = heap_alloc_zero(This->sinks_size*sizeof(*This->sinks)); + i = 0; + } + + This->sinks[i] = sink; + if (cookie) *cookie = i + 1; + + return S_OK; } static HRESULT WINAPI rowpos_cp_Unadvise(IConnectionPoint *iface, DWORD cookie) { rowpos_cp *This = impl_from_IConnectionPoint(iface); - FIXME("(%p)->(%d): stub\n", This, cookie); - return E_NOTIMPL; + + TRACE("(%p)->(%d)\n", This, cookie); + + if (!cookie || cookie > This->sinks_size || !This->sinks[cookie-1]) + return CONNECT_E_NOCONNECTION; + + IRowPositionChange_Release(This->sinks[cookie-1]); + This->sinks[cookie-1] = NULL; + + return S_OK; } static HRESULT WINAPI rowpos_cp_EnumConnections(IConnectionPoint *iface, IEnumConnections **enum_c) @@ -300,6 +349,19 @@ static void rowposchange_cp_init(rowpos_cp *cp, rowpos *container) { cp->IConnectionPoint_iface.lpVtbl = &rowpos_cp_vtbl; cp->container = container; + cp->sinks = NULL; + cp->sinks_size = 0; +} + +void rowposchange_cp_destroy(rowpos_cp *cp) +{ + DWORD i; + for (i = 0; i < cp->sinks_size; i++) + { + if (cp->sinks[i]) + IRowPositionChange_Release(cp->sinks[i]); + } + heap_free(cp->sinks); } HRESULT create_oledb_rowpos(IUnknown *outer, void **obj)