gdiplus: Implement transform matrix for line gradient brushes.
[wine.git] / dlls / oledb32 / rowpos.c
blobc1cee127e8492e052441122e9ded3cfa72f58990
1 /* OLE DB Row Position library
3 * Copyright 2013 Nikolay Sivov
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #define COBJMACROS
22 #include "windef.h"
23 #include "ole2.h"
24 #include "olectl.h"
26 #include "oledb.h"
27 #include "oledberr.h"
29 #include "oledb_private.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(oledb);
34 typedef struct rowpos rowpos;
35 typedef struct
37 IConnectionPoint IConnectionPoint_iface;
38 rowpos *container;
39 IRowPositionChange **sinks;
40 DWORD sinks_size;
41 } rowpos_cp;
43 struct rowpos
45 IRowPosition IRowPosition_iface;
46 IConnectionPointContainer IConnectionPointContainer_iface;
47 LONG ref;
49 IRowset *rowset;
50 IChapteredRowset *chrst;
51 HROW row;
52 HCHAPTER chapter;
53 DBPOSITIONFLAGS flags;
54 BOOL cleared;
55 rowpos_cp cp;
58 static void rowposchange_cp_destroy(rowpos_cp*);
60 static inline rowpos *impl_from_IRowPosition(IRowPosition *iface)
62 return CONTAINING_RECORD(iface, rowpos, IRowPosition_iface);
65 static inline rowpos *impl_from_IConnectionPointContainer(IConnectionPointContainer *iface)
67 return CONTAINING_RECORD(iface, rowpos, IConnectionPointContainer_iface);
70 static inline rowpos_cp *impl_from_IConnectionPoint(IConnectionPoint *iface)
72 return CONTAINING_RECORD(iface, rowpos_cp, IConnectionPoint_iface);
75 static HRESULT rowpos_fireevent(rowpos *rp, DBREASON reason, DBEVENTPHASE phase)
77 BOOL cant_deny = phase == DBEVENTPHASE_FAILEDTODO || phase == DBEVENTPHASE_SYNCHAFTER;
78 HRESULT hr = S_OK;
79 DWORD i;
81 for (i = 0; i < rp->cp.sinks_size; i++)
82 if (rp->cp.sinks[i])
84 hr = IRowPositionChange_OnRowPositionChange(rp->cp.sinks[i], reason, phase, cant_deny);
85 if (phase == DBEVENTPHASE_FAILEDTODO) return DB_E_CANCELED;
86 if (hr != S_OK) return hr;
89 return hr;
92 static void rowpos_clearposition(rowpos *rp)
94 if (!rp->cleared)
96 if (rp->rowset)
97 IRowset_ReleaseRows(rp->rowset, 1, &rp->row, NULL, NULL, NULL);
98 if (rp->chrst)
99 IChapteredRowset_ReleaseChapter(rp->chrst, rp->chapter, NULL);
102 rp->row = DB_NULL_HROW;
103 rp->chapter = DB_NULL_HCHAPTER;
104 rp->flags = DBPOSITION_NOROW;
107 static HRESULT WINAPI rowpos_QueryInterface(IRowPosition* iface, REFIID riid, void **obj)
109 rowpos *This = impl_from_IRowPosition(iface);
111 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), obj);
113 *obj = NULL;
115 if (IsEqualIID(riid, &IID_IUnknown) ||
116 IsEqualIID(riid, &IID_IRowPosition))
118 *obj = iface;
120 else if (IsEqualIID(riid, &IID_IConnectionPointContainer))
122 *obj = &This->IConnectionPointContainer_iface;
124 else
126 FIXME("interface %s not implemented\n", debugstr_guid(riid));
127 return E_NOINTERFACE;
130 IRowPosition_AddRef(iface);
131 return S_OK;
134 static ULONG WINAPI rowpos_AddRef(IRowPosition* iface)
136 rowpos *This = impl_from_IRowPosition(iface);
137 ULONG ref = InterlockedIncrement(&This->ref);
138 TRACE("(%p)->(%d)\n", This, ref);
139 return ref;
142 static ULONG WINAPI rowpos_Release(IRowPosition* iface)
144 rowpos *This = impl_from_IRowPosition(iface);
145 LONG ref = InterlockedDecrement(&This->ref);
147 TRACE("(%p)->(%d)\n", This, ref);
149 if (ref == 0)
151 if (This->rowset) IRowset_Release(This->rowset);
152 if (This->chrst) IChapteredRowset_Release(This->chrst);
153 rowposchange_cp_destroy(&This->cp);
154 heap_free(This);
157 return ref;
160 static HRESULT WINAPI rowpos_ClearRowPosition(IRowPosition* iface)
162 rowpos *This = impl_from_IRowPosition(iface);
163 HRESULT hr;
165 TRACE("(%p)\n", This);
167 if (!This->rowset) return E_UNEXPECTED;
169 hr = rowpos_fireevent(This, DBREASON_ROWPOSITION_CLEARED, DBEVENTPHASE_OKTODO);
170 if (hr != S_OK)
171 return rowpos_fireevent(This, DBREASON_ROWPOSITION_CLEARED, DBEVENTPHASE_FAILEDTODO);
173 hr = rowpos_fireevent(This, DBREASON_ROWPOSITION_CLEARED, DBEVENTPHASE_ABOUTTODO);
174 if (hr != S_OK)
175 return rowpos_fireevent(This, DBREASON_ROWPOSITION_CLEARED, DBEVENTPHASE_FAILEDTODO);
177 rowpos_clearposition(This);
178 This->cleared = TRUE;
179 return S_OK;
182 static HRESULT WINAPI rowpos_GetRowPosition(IRowPosition *iface, HCHAPTER *chapter,
183 HROW *row, DBPOSITIONFLAGS *flags)
185 rowpos *This = impl_from_IRowPosition(iface);
187 TRACE("(%p)->(%p %p %p)\n", This, chapter, row, flags);
189 *chapter = This->chapter;
190 *row = This->row;
191 *flags = This->flags;
193 if (!This->rowset) return E_UNEXPECTED;
195 return S_OK;
198 static HRESULT WINAPI rowpos_GetRowset(IRowPosition *iface, REFIID riid, IUnknown **rowset)
200 rowpos *This = impl_from_IRowPosition(iface);
202 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), rowset);
204 if (!This->rowset) return E_UNEXPECTED;
205 return IRowset_QueryInterface(This->rowset, riid, (void**)rowset);
208 static HRESULT WINAPI rowpos_Initialize(IRowPosition *iface, IUnknown *rowset)
210 rowpos *This = impl_from_IRowPosition(iface);
211 HRESULT hr;
213 TRACE("(%p)->(%p)\n", This, rowset);
215 if (This->rowset) return DB_E_ALREADYINITIALIZED;
217 hr = IUnknown_QueryInterface(rowset, &IID_IRowset, (void**)&This->rowset);
218 if (FAILED(hr)) return hr;
220 /* this one is optional */
221 IUnknown_QueryInterface(rowset, &IID_IChapteredRowset, (void**)&This->chrst);
222 return S_OK;
225 static HRESULT WINAPI rowpos_SetRowPosition(IRowPosition *iface, HCHAPTER chapter,
226 HROW row, DBPOSITIONFLAGS flags)
228 rowpos *This = impl_from_IRowPosition(iface);
229 DBREASON reason;
230 HRESULT hr;
232 TRACE("(%p)->(%lx %lx %d)\n", This, chapter, row, flags);
234 if (!This->cleared) return E_UNEXPECTED;
236 hr = IRowset_AddRefRows(This->rowset, 1, &row, NULL, NULL);
237 if (FAILED(hr)) return hr;
239 if (This->chrst)
241 hr = IChapteredRowset_AddRefChapter(This->chrst, chapter, NULL);
242 if (FAILED(hr))
244 IRowset_ReleaseRows(This->rowset, 1, &row, NULL, NULL, NULL);
245 return hr;
249 reason = This->chrst ? DBREASON_ROWPOSITION_CHAPTERCHANGED : DBREASON_ROWPOSITION_CHANGED;
250 hr = rowpos_fireevent(This, reason, DBEVENTPHASE_SYNCHAFTER);
251 if (hr != S_OK)
253 IRowset_ReleaseRows(This->rowset, 1, &row, NULL, NULL, NULL);
254 if (This->chrst)
255 IChapteredRowset_ReleaseChapter(This->chrst, chapter, NULL);
256 return rowpos_fireevent(This, reason, DBEVENTPHASE_FAILEDTODO);
258 else
259 rowpos_fireevent(This, reason, DBEVENTPHASE_DIDEVENT);
261 /* previously set chapter and row are released with ClearRowPosition() */
262 This->chapter = chapter;
263 This->row = row;
264 This->flags = flags;
265 This->cleared = FALSE;
267 return S_OK;
270 static const struct IRowPositionVtbl rowpos_vtbl =
272 rowpos_QueryInterface,
273 rowpos_AddRef,
274 rowpos_Release,
275 rowpos_ClearRowPosition,
276 rowpos_GetRowPosition,
277 rowpos_GetRowset,
278 rowpos_Initialize,
279 rowpos_SetRowPosition
282 static HRESULT WINAPI cpc_QueryInterface(IConnectionPointContainer *iface, REFIID riid, void **obj)
284 rowpos *This = impl_from_IConnectionPointContainer(iface);
285 return IRowPosition_QueryInterface(&This->IRowPosition_iface, riid, obj);
288 static ULONG WINAPI cpc_AddRef(IConnectionPointContainer *iface)
290 rowpos *This = impl_from_IConnectionPointContainer(iface);
291 return IRowPosition_AddRef(&This->IRowPosition_iface);
294 static ULONG WINAPI cpc_Release(IConnectionPointContainer *iface)
296 rowpos *This = impl_from_IConnectionPointContainer(iface);
297 return IRowPosition_Release(&This->IRowPosition_iface);
300 static HRESULT WINAPI cpc_EnumConnectionPoints(IConnectionPointContainer *iface, IEnumConnectionPoints **enum_points)
302 rowpos *This = impl_from_IConnectionPointContainer(iface);
303 FIXME("(%p)->(%p): stub\n", This, enum_points);
304 return E_NOTIMPL;
307 static HRESULT WINAPI cpc_FindConnectionPoint(IConnectionPointContainer *iface, REFIID riid, IConnectionPoint **point)
309 rowpos *This = impl_from_IConnectionPointContainer(iface);
311 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), point);
313 if (IsEqualIID(riid, &IID_IRowPositionChange))
315 *point = &This->cp.IConnectionPoint_iface;
316 IConnectionPoint_AddRef(*point);
317 return S_OK;
319 else
321 FIXME("unsupported riid %s\n", debugstr_guid(riid));
322 return CONNECT_E_NOCONNECTION;
326 static const struct IConnectionPointContainerVtbl rowpos_cpc_vtbl =
328 cpc_QueryInterface,
329 cpc_AddRef,
330 cpc_Release,
331 cpc_EnumConnectionPoints,
332 cpc_FindConnectionPoint
335 static HRESULT WINAPI rowpos_cp_QueryInterface(IConnectionPoint *iface, REFIID riid, void **obj)
337 rowpos_cp *This = impl_from_IConnectionPoint(iface);
338 return IConnectionPointContainer_QueryInterface(&This->container->IConnectionPointContainer_iface, riid, obj);
341 static ULONG WINAPI rowpos_cp_AddRef(IConnectionPoint *iface)
343 rowpos_cp *This = impl_from_IConnectionPoint(iface);
344 return IConnectionPointContainer_AddRef(&This->container->IConnectionPointContainer_iface);
347 static ULONG WINAPI rowpos_cp_Release(IConnectionPoint *iface)
349 rowpos_cp *This = impl_from_IConnectionPoint(iface);
350 return IConnectionPointContainer_Release(&This->container->IConnectionPointContainer_iface);
353 static HRESULT WINAPI rowpos_cp_GetConnectionInterface(IConnectionPoint *iface, IID *iid)
355 rowpos_cp *This = impl_from_IConnectionPoint(iface);
357 TRACE("(%p)->(%p)\n", This, iid);
359 if (!iid) return E_POINTER;
361 *iid = IID_IRowPositionChange;
362 return S_OK;
365 static HRESULT WINAPI rowpos_cp_GetConnectionPointContainer(IConnectionPoint *iface, IConnectionPointContainer **container)
367 rowpos_cp *This = impl_from_IConnectionPoint(iface);
369 TRACE("(%p)->(%p)\n", This, container);
371 if (!container) return E_POINTER;
373 *container = &This->container->IConnectionPointContainer_iface;
374 IConnectionPointContainer_AddRef(*container);
375 return S_OK;
378 static HRESULT WINAPI rowpos_cp_Advise(IConnectionPoint *iface, IUnknown *unksink, DWORD *cookie)
380 rowpos_cp *This = impl_from_IConnectionPoint(iface);
381 IRowPositionChange *sink;
382 HRESULT hr;
383 DWORD i;
385 TRACE("(%p)->(%p %p)\n", This, unksink, cookie);
387 if (!cookie) return E_POINTER;
389 hr = IUnknown_QueryInterface(unksink, &IID_IRowPositionChange, (void**)&sink);
390 if (FAILED(hr))
392 FIXME("sink doesn't support IRowPositionChange\n");
393 return CONNECT_E_CANNOTCONNECT;
396 if (This->sinks)
398 for (i = 0; i < This->sinks_size; i++)
400 if (!This->sinks[i])
401 break;
404 if (i == This->sinks_size)
406 This->sinks_size *= 2;
407 This->sinks = heap_realloc_zero(This->sinks, This->sinks_size*sizeof(*This->sinks));
410 else
412 This->sinks_size = 10;
413 This->sinks = heap_alloc_zero(This->sinks_size*sizeof(*This->sinks));
414 i = 0;
417 This->sinks[i] = sink;
418 if (cookie) *cookie = i + 1;
420 return S_OK;
423 static HRESULT WINAPI rowpos_cp_Unadvise(IConnectionPoint *iface, DWORD cookie)
425 rowpos_cp *This = impl_from_IConnectionPoint(iface);
427 TRACE("(%p)->(%d)\n", This, cookie);
429 if (!cookie || cookie > This->sinks_size || !This->sinks[cookie-1])
430 return CONNECT_E_NOCONNECTION;
432 IRowPositionChange_Release(This->sinks[cookie-1]);
433 This->sinks[cookie-1] = NULL;
435 return S_OK;
438 static HRESULT WINAPI rowpos_cp_EnumConnections(IConnectionPoint *iface, IEnumConnections **enum_c)
440 rowpos_cp *This = impl_from_IConnectionPoint(iface);
441 FIXME("(%p)->(%p): stub\n", This, enum_c);
442 return E_NOTIMPL;
445 static const struct IConnectionPointVtbl rowpos_cp_vtbl =
447 rowpos_cp_QueryInterface,
448 rowpos_cp_AddRef,
449 rowpos_cp_Release,
450 rowpos_cp_GetConnectionInterface,
451 rowpos_cp_GetConnectionPointContainer,
452 rowpos_cp_Advise,
453 rowpos_cp_Unadvise,
454 rowpos_cp_EnumConnections
457 static void rowposchange_cp_init(rowpos_cp *cp, rowpos *container)
459 cp->IConnectionPoint_iface.lpVtbl = &rowpos_cp_vtbl;
460 cp->container = container;
461 cp->sinks = NULL;
462 cp->sinks_size = 0;
465 void rowposchange_cp_destroy(rowpos_cp *cp)
467 DWORD i;
468 for (i = 0; i < cp->sinks_size; i++)
470 if (cp->sinks[i])
471 IRowPositionChange_Release(cp->sinks[i]);
473 heap_free(cp->sinks);
476 HRESULT create_oledb_rowpos(IUnknown *outer, void **obj)
478 rowpos *This;
480 TRACE("(%p, %p)\n", outer, obj);
482 *obj = NULL;
484 if(outer) return CLASS_E_NOAGGREGATION;
486 This = heap_alloc(sizeof(*This));
487 if(!This) return E_OUTOFMEMORY;
489 This->IRowPosition_iface.lpVtbl = &rowpos_vtbl;
490 This->IConnectionPointContainer_iface.lpVtbl = &rowpos_cpc_vtbl;
491 This->ref = 1;
492 This->rowset = NULL;
493 This->chrst = NULL;
494 This->cleared = FALSE;
495 rowpos_clearposition(This);
496 rowposchange_cp_init(&This->cp, This);
498 *obj = &This->IRowPosition_iface;
500 return S_OK;