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
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
);
44 DISPPARAMS dispparams
;
45 IUnknown
*custom_error
;
49 typedef struct errorrecords
51 IErrorInfo IErrorInfo_iface
;
52 IErrorRecords IErrorRecords_iface
;
55 struct ErrorEntry
*records
;
56 unsigned int allocated
;
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
);
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
;
88 IUnknown_AddRef( (IUnknown
*)*ppvoid
);
92 FIXME("interface %s not implemented\n", debugstr_guid(riid
));
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);
114 for (i
= 0; i
< This
->count
; i
++)
116 DISPPARAMS
*dispparams
= &This
->records
[i
].dispparams
;
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
);
133 static HRESULT WINAPI
errorrecords_GetGUID(IErrorInfo
* iface
, GUID
*guid
)
135 errorrecords
*This
= impl_from_IErrorInfo(iface
);
137 TRACE("(%p)->(%p)\n", This
, guid
);
147 static HRESULT WINAPI
errorrecords_GetSource(IErrorInfo
* iface
, BSTR
*source
)
149 errorrecords
*This
= impl_from_IErrorInfo(iface
);
151 TRACE("(%p)->(%p)\n", This
, source
);
161 static HRESULT WINAPI
errorrecords_GetDescription(IErrorInfo
* iface
, BSTR
*description
)
163 errorrecords
*This
= impl_from_IErrorInfo(iface
);
165 TRACE("(%p)->(%p)\n", This
, description
);
175 static HRESULT WINAPI
errorrecords_GetHelpFile(IErrorInfo
* iface
, BSTR
*helpfile
)
177 errorrecords
*This
= impl_from_IErrorInfo(iface
);
179 TRACE("(%p)->(%p)\n", This
, helpfile
);
189 static HRESULT WINAPI
errorrecords_GetHelpContext(IErrorInfo
* iface
, DWORD
*context
)
191 errorrecords
*This
= impl_from_IErrorInfo(iface
);
193 TRACE("(%p)->(%p)\n", This
, context
);
203 static const IErrorInfoVtbl ErrorInfoVtbl
=
205 errorrecords_QueryInterface
,
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
)
239 memset(dest
, 0, sizeof(*dest
));
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
]);
257 dest
->rgdispidNamedArgs
= CoTaskMemAlloc(dest
->cNamedArgs
* sizeof(*dest
->rgdispidNamedArgs
));
258 memcpy(dest
->rgdispidNamedArgs
, src
->rgdispidNamedArgs
, dest
->cNamedArgs
* sizeof(*dest
->rgdispidNamedArgs
));
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
;
271 TRACE("(%p)->(%p %d %p %p %d)\n", This
, pErrorInfo
, dwLookupID
, pdispparams
, punkCustomError
, dwDynamicErrorID
);
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
));
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
)))
302 entry
->custom_error
= punkCustomError
;
303 if (entry
->custom_error
)
304 IUnknown_AddRef(entry
->custom_error
);
305 entry
->lookupID
= dwDynamicErrorID
;
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
);
321 if (index
>= This
->count
)
322 return DB_E_BADRECORDNUM
;
324 index
= This
->count
- index
- 1;
325 *info
= This
->records
[index
].info
;
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
);
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
);
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
);
361 if (index
>= This
->count
)
362 return DB_E_BADRECORDNUM
;
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
);
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
);
392 *count
= This
->count
;
394 TRACE("<--(%u)\n", *count
);
399 static const IErrorRecordsVtbl ErrorRecordsVtbl
=
401 errorrec_QueryInterface
,
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
)
416 TRACE("(%p, %p)\n", outer
, obj
);
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
;
429 This
->records
= NULL
;
433 *obj
= &This
->IErrorInfo_iface
;