winejoystick: Fix a crash on accessing a CFArray past its end due to an off-by-one...
[wine/multimedia.git] / dlls / oledb32 / errorinfo.c
blob4a2a1e2d1e4a2c39e1d4688dc59276ad16f14799
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/unicode.h"
35 #include "wine/list.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(oledb);
41 struct ErrorEntry
43 struct list entry;
44 ERRORINFO info;
45 DISPPARAMS dispparams;
46 IUnknown *unknown;
47 DWORD lookupID;
50 typedef struct ErrorInfoImpl
52 IErrorInfo IErrorInfo_iface;
53 IErrorRecords IErrorRecords_iface;
54 LONG ref;
56 GUID m_Guid;
57 BSTR source;
58 BSTR description;
59 BSTR help_file;
60 DWORD help_context;
62 struct list errors;
63 } ErrorInfoImpl;
65 static inline ErrorInfoImpl *impl_from_IErrorInfo( IErrorInfo *iface )
67 return CONTAINING_RECORD(iface, ErrorInfoImpl, IErrorInfo_iface);
70 static inline ErrorInfoImpl *impl_from_IErrorRecords( IErrorRecords *iface )
72 return CONTAINING_RECORD(iface, ErrorInfoImpl, IErrorRecords_iface);
75 static HRESULT WINAPI IErrorInfoImpl_QueryInterface(IErrorInfo* iface, REFIID riid, void **ppvoid)
77 ErrorInfoImpl *This = impl_from_IErrorInfo(iface);
78 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid),ppvoid);
80 *ppvoid = NULL;
82 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IErrorInfo))
84 *ppvoid = &This->IErrorInfo_iface;
86 else if (IsEqualIID(riid, &IID_IErrorRecords))
88 *ppvoid = &This->IErrorRecords_iface;
91 if(*ppvoid)
93 IUnknown_AddRef( (IUnknown*)*ppvoid );
94 return S_OK;
97 FIXME("interface %s not implemented\n", debugstr_guid(riid));
98 return E_NOINTERFACE;
101 static ULONG WINAPI IErrorInfoImpl_AddRef(IErrorInfo* iface)
103 ErrorInfoImpl *This = impl_from_IErrorInfo(iface);
104 TRACE("(%p)->%u\n",This,This->ref);
105 return InterlockedIncrement(&This->ref);
108 static ULONG WINAPI IErrorInfoImpl_Release(IErrorInfo* iface)
110 ErrorInfoImpl *This = impl_from_IErrorInfo(iface);
111 ULONG ref = InterlockedDecrement(&This->ref);
112 struct ErrorEntry *cursor, *cursor2;
114 TRACE("(%p)->%u\n",This,ref+1);
116 if (!ref)
118 SysFreeString(This->source);
119 SysFreeString(This->description);
120 SysFreeString(This->help_file);
122 LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->errors, struct ErrorEntry, entry)
124 list_remove(&cursor->entry);
125 if(cursor->unknown)
126 IUnknown_Release(cursor->unknown);
128 heap_free(cursor);
130 heap_free(This);
132 return ref;
135 static HRESULT WINAPI IErrorInfoImpl_GetGUID(IErrorInfo* iface, GUID * pGUID)
137 ErrorInfoImpl *This = impl_from_IErrorInfo(iface);
139 TRACE("(%p)\n",This);
141 if(!pGUID )
142 return E_INVALIDARG;
144 *pGUID = This->m_Guid;
146 return S_OK;
149 static HRESULT WINAPI IErrorInfoImpl_GetSource(IErrorInfo* iface, BSTR *pBstrSource)
151 ErrorInfoImpl *This = impl_from_IErrorInfo(iface);
153 TRACE("(%p)->(%p)\n",This, pBstrSource);
155 if (pBstrSource == NULL)
156 return E_INVALIDARG;
158 *pBstrSource = SysAllocString(This->source);
160 return S_OK;
163 static HRESULT WINAPI IErrorInfoImpl_GetDescription(IErrorInfo* iface, BSTR *pBstrDescription)
165 ErrorInfoImpl *This = impl_from_IErrorInfo(iface);
167 TRACE("(%p)->(%p)\n",This, pBstrDescription);
169 if (pBstrDescription == NULL)
170 return E_INVALIDARG;
172 *pBstrDescription = SysAllocString(This->description);
174 return S_OK;
177 static HRESULT WINAPI IErrorInfoImpl_GetHelpFile(IErrorInfo* iface, BSTR *pBstrHelpFile)
179 ErrorInfoImpl *This = impl_from_IErrorInfo(iface);
181 TRACE("(%p)->(%p)\n",This, pBstrHelpFile);
183 if (pBstrHelpFile == NULL)
184 return E_INVALIDARG;
186 *pBstrHelpFile = SysAllocString(This->help_file);
188 return S_OK;
191 static HRESULT WINAPI IErrorInfoImpl_GetHelpContext(IErrorInfo* iface, DWORD *pdwHelpContext)
193 ErrorInfoImpl *This = impl_from_IErrorInfo(iface);
195 TRACE("(%p)->(%p)\n",This, pdwHelpContext);
197 if (pdwHelpContext == NULL)
198 return E_INVALIDARG;
200 *pdwHelpContext = This->help_context;
202 return S_OK;
205 static const IErrorInfoVtbl ErrorInfoVtbl =
207 IErrorInfoImpl_QueryInterface,
208 IErrorInfoImpl_AddRef,
209 IErrorInfoImpl_Release,
210 IErrorInfoImpl_GetGUID,
211 IErrorInfoImpl_GetSource,
212 IErrorInfoImpl_GetDescription,
213 IErrorInfoImpl_GetHelpFile,
214 IErrorInfoImpl_GetHelpContext
217 static HRESULT WINAPI errorrec_QueryInterface(IErrorRecords *iface, REFIID riid, void **ppvObject)
219 ErrorInfoImpl *This = impl_from_IErrorRecords(iface);
220 return IErrorInfo_QueryInterface(&This->IErrorInfo_iface, riid, ppvObject);
223 static ULONG WINAPI WINAPI errorrec_AddRef(IErrorRecords *iface)
225 ErrorInfoImpl *This = impl_from_IErrorRecords(iface);
226 return IErrorInfo_AddRef(&This->IErrorInfo_iface);
229 static ULONG WINAPI WINAPI errorrec_Release(IErrorRecords *iface)
231 ErrorInfoImpl *This = impl_from_IErrorRecords(iface);
232 return IErrorInfo_Release(&This->IErrorInfo_iface);
235 static HRESULT WINAPI errorrec_AddErrorRecord(IErrorRecords *iface, ERRORINFO *pErrorInfo,
236 DWORD dwLookupID, DISPPARAMS *pdispparams, IUnknown *punkCustomError, DWORD dwDynamicErrorID)
238 ErrorInfoImpl *This = impl_from_IErrorRecords(iface);
239 struct ErrorEntry *entry;
241 TRACE("(%p)->(%p %d %p %p %d)\n", This, pErrorInfo, dwLookupID, pdispparams, punkCustomError, dwDynamicErrorID);
243 if(!pErrorInfo)
244 return E_INVALIDARG;
246 entry = heap_alloc(sizeof(*entry));
247 if(!entry)
248 return E_OUTOFMEMORY;
250 entry->info = *pErrorInfo;
251 if(pdispparams)
252 entry->dispparams = *pdispparams;
253 entry->unknown = punkCustomError;
254 if(entry->unknown)
255 IUnknown_AddRef(entry->unknown);
256 entry->lookupID = dwDynamicErrorID;
258 list_add_head(&This->errors, &entry->entry);
260 return S_OK;
263 static HRESULT WINAPI errorrec_GetBasicErrorInfo(IErrorRecords *iface, ULONG ulRecordNum,
264 ERRORINFO *pErrorInfo)
266 ErrorInfoImpl *This = impl_from_IErrorRecords(iface);
268 FIXME("(%p)->(%d %p)\n", This, ulRecordNum, pErrorInfo);
270 if(!pErrorInfo)
271 return E_INVALIDARG;
273 if(ulRecordNum > list_count(&This->errors))
274 return DB_E_BADRECORDNUM;
276 return E_NOTIMPL;
279 static HRESULT WINAPI errorrec_GetCustomErrorObject(IErrorRecords *iface, ULONG ulRecordNum,
280 REFIID riid, IUnknown **ppObject)
282 ErrorInfoImpl *This = impl_from_IErrorRecords(iface);
284 FIXME("(%p)->(%d %s, %p)\n", This, ulRecordNum, debugstr_guid(riid), ppObject);
286 if (!ppObject)
287 return E_INVALIDARG;
289 *ppObject = NULL;
291 if(ulRecordNum > list_count(&This->errors))
292 return DB_E_BADRECORDNUM;
294 return E_NOTIMPL;
297 static HRESULT WINAPI errorrec_GetErrorInfo(IErrorRecords *iface, ULONG ulRecordNum,
298 LCID lcid, IErrorInfo **ppErrorInfo)
300 ErrorInfoImpl *This = impl_from_IErrorRecords(iface);
302 FIXME("(%p)->(%d %d, %p)\n", This, ulRecordNum, lcid, ppErrorInfo);
304 if (!ppErrorInfo)
305 return E_INVALIDARG;
307 if(ulRecordNum > list_count(&This->errors))
308 return DB_E_BADRECORDNUM;
310 return E_NOTIMPL;
313 static HRESULT WINAPI errorrec_GetErrorParameters(IErrorRecords *iface, ULONG ulRecordNum,
314 DISPPARAMS *pdispparams)
316 ErrorInfoImpl *This = impl_from_IErrorRecords(iface);
318 FIXME("(%p)->(%d %p)\n", This, ulRecordNum, pdispparams);
320 if (!pdispparams)
321 return E_INVALIDARG;
323 if(ulRecordNum > list_count(&This->errors))
324 return DB_E_BADRECORDNUM;
326 return E_NOTIMPL;
329 static HRESULT WINAPI errorrec_GetRecordCount(IErrorRecords *iface, ULONG *records)
331 ErrorInfoImpl *This = impl_from_IErrorRecords(iface);
333 TRACE("(%p)->(%p)\n", This, records);
335 if(!records)
336 return E_INVALIDARG;
338 *records = list_count(&This->errors);
340 TRACE("<--(%d)\n", *records);
342 return S_OK;
345 static const IErrorRecordsVtbl ErrorRecordsVtbl =
347 errorrec_QueryInterface,
348 errorrec_AddRef,
349 errorrec_Release,
350 errorrec_AddErrorRecord,
351 errorrec_GetBasicErrorInfo,
352 errorrec_GetCustomErrorObject,
353 errorrec_GetErrorInfo,
354 errorrec_GetErrorParameters,
355 errorrec_GetRecordCount
358 HRESULT create_error_info(IUnknown *outer, void **obj)
360 ErrorInfoImpl *This;
362 TRACE("(%p, %p)\n", outer, obj);
364 *obj = NULL;
366 if(outer) return CLASS_E_NOAGGREGATION;
368 This = heap_alloc(sizeof(*This));
369 if(!This) return E_OUTOFMEMORY;
371 This->IErrorInfo_iface.lpVtbl = &ErrorInfoVtbl;
372 This->IErrorRecords_iface.lpVtbl = &ErrorRecordsVtbl;
373 This->ref = 1;
374 This->source = NULL;
375 This->description = NULL;
376 This->help_file = NULL;
377 This->help_context = 0;
379 list_init(&This->errors);
381 *obj = &This->IErrorInfo_iface;
383 return S_OK;