mfplat: Read queue subscriber within the critical section.
[wine/zf.git] / dlls / oledb32 / errorinfo.c
blob9987b2113bfd333a1e11ebf9b5d616e88d3f76f3
1 /* OLE DB ErrorInfo
3 * Copyright 2013 Alistair Leslie-Hughes
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
19 #include <stdarg.h>
20 #include <string.h>
22 #define COBJMACROS
24 #include "windef.h"
25 #include "winbase.h"
26 #include "objbase.h"
27 #include "oleauto.h"
28 #include "winerror.h"
29 #include "oledb.h"
30 #include "oledberr.h"
32 #include "oledb_private.h"
34 #include "wine/heap.h"
35 #include "wine/list.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(oledb);
41 struct ErrorEntry
43 ERRORINFO info;
44 DISPPARAMS dispparams;
45 IUnknown *custom_error;
46 DWORD lookupID;
49 typedef struct errorrecords
51 IErrorInfo IErrorInfo_iface;
52 IErrorRecords IErrorRecords_iface;
53 LONG ref;
55 struct ErrorEntry *records;
56 unsigned int allocated;
57 unsigned int count;
58 } errorrecords;
60 static inline errorrecords *impl_from_IErrorInfo( IErrorInfo *iface )
62 return CONTAINING_RECORD(iface, errorrecords, IErrorInfo_iface);
65 static inline errorrecords *impl_from_IErrorRecords( IErrorRecords *iface )
67 return CONTAINING_RECORD(iface, errorrecords, IErrorRecords_iface);
70 static HRESULT WINAPI errorrecords_QueryInterface(IErrorInfo* iface, REFIID riid, void **ppvoid)
72 errorrecords *This = impl_from_IErrorInfo(iface);
73 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid),ppvoid);
75 *ppvoid = NULL;
77 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IErrorInfo))
79 *ppvoid = &This->IErrorInfo_iface;
81 else if (IsEqualIID(riid, &IID_IErrorRecords))
83 *ppvoid = &This->IErrorRecords_iface;
86 if(*ppvoid)
88 IUnknown_AddRef( (IUnknown*)*ppvoid );
89 return S_OK;
92 FIXME("interface %s not implemented\n", debugstr_guid(riid));
93 return E_NOINTERFACE;
96 static ULONG WINAPI errorrecords_AddRef(IErrorInfo* iface)
98 errorrecords *This = impl_from_IErrorInfo(iface);
99 TRACE("(%p)->%u\n",This,This->ref);
100 return InterlockedIncrement(&This->ref);
103 static ULONG WINAPI errorrecords_Release(IErrorInfo* iface)
105 errorrecords *This = impl_from_IErrorInfo(iface);
106 ULONG ref = InterlockedDecrement(&This->ref);
108 TRACE("(%p)->%u\n",This,ref+1);
110 if (!ref)
112 unsigned int i;
114 for (i = 0; i < This->count; i++)
116 DISPPARAMS *dispparams = &This->records[i].dispparams;
117 unsigned int j;
119 if (This->records[i].custom_error)
120 IUnknown_Release(This->records[i].custom_error);
122 for (j = 0; j < dispparams->cArgs && dispparams->rgvarg; j++)
123 VariantClear(&dispparams->rgvarg[i]);
124 CoTaskMemFree(dispparams->rgvarg);
125 CoTaskMemFree(dispparams->rgdispidNamedArgs);
127 heap_free(This->records);
128 heap_free(This);
130 return ref;
133 static HRESULT WINAPI errorrecords_GetGUID(IErrorInfo* iface, GUID *guid)
135 errorrecords *This = impl_from_IErrorInfo(iface);
137 TRACE("(%p)->(%p)\n", This, guid);
139 if (!guid)
140 return E_INVALIDARG;
142 *guid = GUID_NULL;
144 return S_OK;
147 static HRESULT WINAPI errorrecords_GetSource(IErrorInfo* iface, BSTR *source)
149 errorrecords *This = impl_from_IErrorInfo(iface);
151 TRACE("(%p)->(%p)\n", This, source);
153 if (!source)
154 return E_INVALIDARG;
156 *source = NULL;
158 return E_FAIL;
161 static HRESULT WINAPI errorrecords_GetDescription(IErrorInfo* iface, BSTR *description)
163 errorrecords *This = impl_from_IErrorInfo(iface);
165 TRACE("(%p)->(%p)\n", This, description);
167 if (!description)
168 return E_INVALIDARG;
170 *description = NULL;
172 return E_FAIL;
175 static HRESULT WINAPI errorrecords_GetHelpFile(IErrorInfo* iface, BSTR *helpfile)
177 errorrecords *This = impl_from_IErrorInfo(iface);
179 TRACE("(%p)->(%p)\n", This, helpfile);
181 if (!helpfile)
182 return E_INVALIDARG;
184 *helpfile = NULL;
186 return E_FAIL;
189 static HRESULT WINAPI errorrecords_GetHelpContext(IErrorInfo* iface, DWORD *context)
191 errorrecords *This = impl_from_IErrorInfo(iface);
193 TRACE("(%p)->(%p)\n", This, context);
195 if (!context)
196 return E_INVALIDARG;
198 *context = 0;
200 return E_FAIL;
203 static const IErrorInfoVtbl ErrorInfoVtbl =
205 errorrecords_QueryInterface,
206 errorrecords_AddRef,
207 errorrecords_Release,
208 errorrecords_GetGUID,
209 errorrecords_GetSource,
210 errorrecords_GetDescription,
211 errorrecords_GetHelpFile,
212 errorrecords_GetHelpContext
215 static HRESULT WINAPI errorrec_QueryInterface(IErrorRecords *iface, REFIID riid, void **ppvObject)
217 errorrecords *This = impl_from_IErrorRecords(iface);
218 return IErrorInfo_QueryInterface(&This->IErrorInfo_iface, riid, ppvObject);
221 static ULONG WINAPI errorrec_AddRef(IErrorRecords *iface)
223 errorrecords *This = impl_from_IErrorRecords(iface);
224 return IErrorInfo_AddRef(&This->IErrorInfo_iface);
227 static ULONG WINAPI errorrec_Release(IErrorRecords *iface)
229 errorrecords *This = impl_from_IErrorRecords(iface);
230 return IErrorInfo_Release(&This->IErrorInfo_iface);
233 static HRESULT dup_dispparams(DISPPARAMS *src, DISPPARAMS *dest)
235 unsigned int i;
237 if (!src)
239 memset(dest, 0, sizeof(*dest));
240 return S_OK;
243 *dest = *src;
245 if (src->cArgs)
247 dest->rgvarg = CoTaskMemAlloc(dest->cArgs * sizeof(*dest->rgvarg));
248 for (i = 0; i < src->cArgs; i++)
250 VariantInit(&dest->rgvarg[i]);
251 VariantCopy(&dest->rgvarg[i], &src->rgvarg[i]);
255 if (src->cNamedArgs)
257 dest->rgdispidNamedArgs = CoTaskMemAlloc(dest->cNamedArgs * sizeof(*dest->rgdispidNamedArgs));
258 memcpy(dest->rgdispidNamedArgs, src->rgdispidNamedArgs, dest->cNamedArgs * sizeof(*dest->rgdispidNamedArgs));
261 return S_OK;
264 static HRESULT WINAPI errorrec_AddErrorRecord(IErrorRecords *iface, ERRORINFO *pErrorInfo,
265 DWORD dwLookupID, DISPPARAMS *pdispparams, IUnknown *punkCustomError, DWORD dwDynamicErrorID)
267 errorrecords *This = impl_from_IErrorRecords(iface);
268 struct ErrorEntry *entry;
269 HRESULT hr;
271 TRACE("(%p)->(%p %d %p %p %d)\n", This, pErrorInfo, dwLookupID, pdispparams, punkCustomError, dwDynamicErrorID);
273 if(!pErrorInfo)
274 return E_INVALIDARG;
276 if (!This->records)
278 const unsigned int initial_size = 16;
279 if (!(This->records = heap_alloc(initial_size * sizeof(*This->records))))
280 return E_OUTOFMEMORY;
282 This->allocated = initial_size;
284 else if (This->count == This->allocated)
286 struct ErrorEntry *new_ptr;
288 new_ptr = heap_realloc(This->records, 2 * This->allocated * sizeof(*This->records));
289 if (!new_ptr)
290 return E_OUTOFMEMORY;
292 This->records = new_ptr;
293 This->allocated *= 2;
296 entry = This->records + This->count;
297 entry->info = *pErrorInfo;
299 if (FAILED(hr = dup_dispparams(pdispparams, &entry->dispparams)))
300 return hr;
302 entry->custom_error = punkCustomError;
303 if (entry->custom_error)
304 IUnknown_AddRef(entry->custom_error);
305 entry->lookupID = dwDynamicErrorID;
307 This->count++;
309 return S_OK;
312 static HRESULT WINAPI errorrec_GetBasicErrorInfo(IErrorRecords *iface, ULONG index, ERRORINFO *info)
314 errorrecords *This = impl_from_IErrorRecords(iface);
316 TRACE("(%p)->(%u %p)\n", This, index, info);
318 if (!info)
319 return E_INVALIDARG;
321 if (index >= This->count)
322 return DB_E_BADRECORDNUM;
324 index = This->count - index - 1;
325 *info = This->records[index].info;
326 return S_OK;
329 static HRESULT WINAPI errorrec_GetCustomErrorObject(IErrorRecords *iface, ULONG index,
330 REFIID riid, IUnknown **object)
332 errorrecords *This = impl_from_IErrorRecords(iface);
334 TRACE("(%p)->(%u %s %p)\n", This, index, debugstr_guid(riid), object);
336 if (!object)
337 return E_INVALIDARG;
339 *object = NULL;
341 if (index >= This->count)
342 return DB_E_BADRECORDNUM;
344 index = This->count - index - 1;
345 if (This->records[index].custom_error)
346 return IUnknown_QueryInterface(This->records[index].custom_error, riid, (void **)object);
347 else
348 return S_OK;
351 static HRESULT WINAPI errorrec_GetErrorInfo(IErrorRecords *iface, ULONG index,
352 LCID lcid, IErrorInfo **ppErrorInfo)
354 errorrecords *This = impl_from_IErrorRecords(iface);
356 FIXME("(%p)->(%u %d, %p)\n", This, index, lcid, ppErrorInfo);
358 if (!ppErrorInfo)
359 return E_INVALIDARG;
361 if (index >= This->count)
362 return DB_E_BADRECORDNUM;
364 return IErrorInfo_QueryInterface(&This->IErrorInfo_iface, &IID_IErrorInfo, (void **)ppErrorInfo);
367 static HRESULT WINAPI errorrec_GetErrorParameters(IErrorRecords *iface, ULONG index, DISPPARAMS *pdispparams)
369 errorrecords *This = impl_from_IErrorRecords(iface);
371 TRACE("(%p)->(%u %p)\n", This, index, pdispparams);
373 if (!pdispparams)
374 return E_INVALIDARG;
376 if (index >= This->count)
377 return DB_E_BADRECORDNUM;
379 index = This->count - index - 1;
380 return dup_dispparams(&This->records[index].dispparams, pdispparams);
383 static HRESULT WINAPI errorrec_GetRecordCount(IErrorRecords *iface, ULONG *count)
385 errorrecords *This = impl_from_IErrorRecords(iface);
387 TRACE("(%p)->(%p)\n", This, count);
389 if(!count)
390 return E_INVALIDARG;
392 *count = This->count;
394 TRACE("<--(%u)\n", *count);
396 return S_OK;
399 static const IErrorRecordsVtbl ErrorRecordsVtbl =
401 errorrec_QueryInterface,
402 errorrec_AddRef,
403 errorrec_Release,
404 errorrec_AddErrorRecord,
405 errorrec_GetBasicErrorInfo,
406 errorrec_GetCustomErrorObject,
407 errorrec_GetErrorInfo,
408 errorrec_GetErrorParameters,
409 errorrec_GetRecordCount
412 HRESULT create_error_info(IUnknown *outer, void **obj)
414 errorrecords *This;
416 TRACE("(%p, %p)\n", outer, obj);
418 *obj = NULL;
420 if(outer) return CLASS_E_NOAGGREGATION;
422 This = heap_alloc(sizeof(*This));
423 if(!This) return E_OUTOFMEMORY;
425 This->IErrorInfo_iface.lpVtbl = &ErrorInfoVtbl;
426 This->IErrorRecords_iface.lpVtbl = &ErrorRecordsVtbl;
427 This->ref = 1;
429 This->records = NULL;
430 This->allocated = 0;
431 This->count = 0;
433 *obj = &This->IErrorInfo_iface;
435 return S_OK;