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/unicode.h"
35 #include "wine/heap.h"
36 #include "wine/list.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(oledb
);
45 DISPPARAMS dispparams
;
46 IUnknown
*custom_error
;
50 typedef struct errorrecords
52 IErrorInfo IErrorInfo_iface
;
53 IErrorRecords IErrorRecords_iface
;
56 struct ErrorEntry
*records
;
57 unsigned int allocated
;
61 static inline errorrecords
*impl_from_IErrorInfo( IErrorInfo
*iface
)
63 return CONTAINING_RECORD(iface
, errorrecords
, IErrorInfo_iface
);
66 static inline errorrecords
*impl_from_IErrorRecords( IErrorRecords
*iface
)
68 return CONTAINING_RECORD(iface
, errorrecords
, IErrorRecords_iface
);
71 static HRESULT WINAPI
errorrecords_QueryInterface(IErrorInfo
* iface
, REFIID riid
, void **ppvoid
)
73 errorrecords
*This
= impl_from_IErrorInfo(iface
);
74 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
),ppvoid
);
78 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IErrorInfo
))
80 *ppvoid
= &This
->IErrorInfo_iface
;
82 else if (IsEqualIID(riid
, &IID_IErrorRecords
))
84 *ppvoid
= &This
->IErrorRecords_iface
;
89 IUnknown_AddRef( (IUnknown
*)*ppvoid
);
93 FIXME("interface %s not implemented\n", debugstr_guid(riid
));
97 static ULONG WINAPI
errorrecords_AddRef(IErrorInfo
* iface
)
99 errorrecords
*This
= impl_from_IErrorInfo(iface
);
100 TRACE("(%p)->%u\n",This
,This
->ref
);
101 return InterlockedIncrement(&This
->ref
);
104 static ULONG WINAPI
errorrecords_Release(IErrorInfo
* iface
)
106 errorrecords
*This
= impl_from_IErrorInfo(iface
);
107 ULONG ref
= InterlockedDecrement(&This
->ref
);
109 TRACE("(%p)->%u\n",This
,ref
+1);
115 for (i
= 0; i
< This
->count
; i
++)
117 DISPPARAMS
*dispparams
= &This
->records
[i
].dispparams
;
120 if (This
->records
[i
].custom_error
)
121 IUnknown_Release(This
->records
[i
].custom_error
);
123 for (j
= 0; j
< dispparams
->cArgs
&& dispparams
->rgvarg
; j
++)
124 VariantClear(&dispparams
->rgvarg
[i
]);
125 CoTaskMemFree(dispparams
->rgvarg
);
126 CoTaskMemFree(dispparams
->rgdispidNamedArgs
);
128 heap_free(This
->records
);
134 static HRESULT WINAPI
errorrecords_GetGUID(IErrorInfo
* iface
, GUID
*guid
)
136 errorrecords
*This
= impl_from_IErrorInfo(iface
);
138 TRACE("(%p)->(%p)\n", This
, guid
);
148 static HRESULT WINAPI
errorrecords_GetSource(IErrorInfo
* iface
, BSTR
*source
)
150 errorrecords
*This
= impl_from_IErrorInfo(iface
);
152 TRACE("(%p)->(%p)\n", This
, source
);
162 static HRESULT WINAPI
errorrecords_GetDescription(IErrorInfo
* iface
, BSTR
*description
)
164 errorrecords
*This
= impl_from_IErrorInfo(iface
);
166 TRACE("(%p)->(%p)\n", This
, description
);
176 static HRESULT WINAPI
errorrecords_GetHelpFile(IErrorInfo
* iface
, BSTR
*helpfile
)
178 errorrecords
*This
= impl_from_IErrorInfo(iface
);
180 TRACE("(%p)->(%p)\n", This
, helpfile
);
190 static HRESULT WINAPI
errorrecords_GetHelpContext(IErrorInfo
* iface
, DWORD
*context
)
192 errorrecords
*This
= impl_from_IErrorInfo(iface
);
194 TRACE("(%p)->(%p)\n", This
, context
);
204 static const IErrorInfoVtbl ErrorInfoVtbl
=
206 errorrecords_QueryInterface
,
208 errorrecords_Release
,
209 errorrecords_GetGUID
,
210 errorrecords_GetSource
,
211 errorrecords_GetDescription
,
212 errorrecords_GetHelpFile
,
213 errorrecords_GetHelpContext
216 static HRESULT WINAPI
errorrec_QueryInterface(IErrorRecords
*iface
, REFIID riid
, void **ppvObject
)
218 errorrecords
*This
= impl_from_IErrorRecords(iface
);
219 return IErrorInfo_QueryInterface(&This
->IErrorInfo_iface
, riid
, ppvObject
);
222 static ULONG WINAPI WINAPI
errorrec_AddRef(IErrorRecords
*iface
)
224 errorrecords
*This
= impl_from_IErrorRecords(iface
);
225 return IErrorInfo_AddRef(&This
->IErrorInfo_iface
);
228 static ULONG WINAPI WINAPI
errorrec_Release(IErrorRecords
*iface
)
230 errorrecords
*This
= impl_from_IErrorRecords(iface
);
231 return IErrorInfo_Release(&This
->IErrorInfo_iface
);
234 static HRESULT
dup_dispparams(DISPPARAMS
*src
, DISPPARAMS
*dest
)
240 memset(dest
, 0, sizeof(*dest
));
248 dest
->rgvarg
= CoTaskMemAlloc(dest
->cArgs
* sizeof(*dest
->rgvarg
));
249 for (i
= 0; i
< src
->cArgs
; i
++)
251 VariantInit(&dest
->rgvarg
[i
]);
252 VariantCopy(&dest
->rgvarg
[i
], &src
->rgvarg
[i
]);
258 dest
->rgdispidNamedArgs
= CoTaskMemAlloc(dest
->cNamedArgs
* sizeof(*dest
->rgdispidNamedArgs
));
259 memcpy(dest
->rgdispidNamedArgs
, src
->rgdispidNamedArgs
, dest
->cNamedArgs
* sizeof(*dest
->rgdispidNamedArgs
));
265 static HRESULT WINAPI
errorrec_AddErrorRecord(IErrorRecords
*iface
, ERRORINFO
*pErrorInfo
,
266 DWORD dwLookupID
, DISPPARAMS
*pdispparams
, IUnknown
*punkCustomError
, DWORD dwDynamicErrorID
)
268 errorrecords
*This
= impl_from_IErrorRecords(iface
);
269 struct ErrorEntry
*entry
;
272 TRACE("(%p)->(%p %d %p %p %d)\n", This
, pErrorInfo
, dwLookupID
, pdispparams
, punkCustomError
, dwDynamicErrorID
);
279 const unsigned int initial_size
= 16;
280 if (!(This
->records
= heap_alloc(initial_size
* sizeof(*This
->records
))))
281 return E_OUTOFMEMORY
;
283 This
->allocated
= initial_size
;
285 else if (This
->count
== This
->allocated
)
287 struct ErrorEntry
*new_ptr
;
289 new_ptr
= heap_realloc(This
->records
, 2 * This
->allocated
* sizeof(*This
->records
));
291 return E_OUTOFMEMORY
;
293 This
->records
= new_ptr
;
294 This
->allocated
*= 2;
297 entry
= This
->records
+ This
->count
;
298 entry
->info
= *pErrorInfo
;
300 if (FAILED(hr
= dup_dispparams(pdispparams
, &entry
->dispparams
)))
303 entry
->custom_error
= punkCustomError
;
304 if (entry
->custom_error
)
305 IUnknown_AddRef(entry
->custom_error
);
306 entry
->lookupID
= dwDynamicErrorID
;
313 static HRESULT WINAPI
errorrec_GetBasicErrorInfo(IErrorRecords
*iface
, ULONG index
, ERRORINFO
*info
)
315 errorrecords
*This
= impl_from_IErrorRecords(iface
);
317 TRACE("(%p)->(%u %p)\n", This
, index
, info
);
322 if (index
>= This
->count
)
323 return DB_E_BADRECORDNUM
;
325 index
= This
->count
- index
- 1;
326 *info
= This
->records
[index
].info
;
330 static HRESULT WINAPI
errorrec_GetCustomErrorObject(IErrorRecords
*iface
, ULONG index
,
331 REFIID riid
, IUnknown
**object
)
333 errorrecords
*This
= impl_from_IErrorRecords(iface
);
335 TRACE("(%p)->(%u %s %p)\n", This
, index
, debugstr_guid(riid
), object
);
342 if (index
>= This
->count
)
343 return DB_E_BADRECORDNUM
;
345 index
= This
->count
- index
- 1;
346 if (This
->records
[index
].custom_error
)
347 return IUnknown_QueryInterface(This
->records
[index
].custom_error
, riid
, (void **)object
);
352 static HRESULT WINAPI
errorrec_GetErrorInfo(IErrorRecords
*iface
, ULONG index
,
353 LCID lcid
, IErrorInfo
**ppErrorInfo
)
355 errorrecords
*This
= impl_from_IErrorRecords(iface
);
357 FIXME("(%p)->(%u %d, %p)\n", This
, index
, lcid
, ppErrorInfo
);
362 if (index
>= This
->count
)
363 return DB_E_BADRECORDNUM
;
368 static HRESULT WINAPI
errorrec_GetErrorParameters(IErrorRecords
*iface
, ULONG index
, DISPPARAMS
*pdispparams
)
370 errorrecords
*This
= impl_from_IErrorRecords(iface
);
372 TRACE("(%p)->(%u %p)\n", This
, index
, pdispparams
);
377 if (index
>= This
->count
)
378 return DB_E_BADRECORDNUM
;
380 index
= This
->count
- index
- 1;
381 return dup_dispparams(&This
->records
[index
].dispparams
, pdispparams
);
384 static HRESULT WINAPI
errorrec_GetRecordCount(IErrorRecords
*iface
, ULONG
*count
)
386 errorrecords
*This
= impl_from_IErrorRecords(iface
);
388 TRACE("(%p)->(%p)\n", This
, count
);
393 *count
= This
->count
;
395 TRACE("<--(%u)\n", *count
);
400 static const IErrorRecordsVtbl ErrorRecordsVtbl
=
402 errorrec_QueryInterface
,
405 errorrec_AddErrorRecord
,
406 errorrec_GetBasicErrorInfo
,
407 errorrec_GetCustomErrorObject
,
408 errorrec_GetErrorInfo
,
409 errorrec_GetErrorParameters
,
410 errorrec_GetRecordCount
413 HRESULT
create_error_info(IUnknown
*outer
, void **obj
)
417 TRACE("(%p, %p)\n", outer
, obj
);
421 if(outer
) return CLASS_E_NOAGGREGATION
;
423 This
= heap_alloc(sizeof(*This
));
424 if(!This
) return E_OUTOFMEMORY
;
426 This
->IErrorInfo_iface
.lpVtbl
= &ErrorInfoVtbl
;
427 This
->IErrorRecords_iface
.lpVtbl
= &ErrorRecordsVtbl
;
430 This
->records
= NULL
;
434 *obj
= &This
->IErrorInfo_iface
;