oledb32: Add some conversions to DBTYPE_R4.
[wine] / dlls / oledb32 / convert.c
1 /* OLE DB Conversion library
2  *
3  * Copyright 2009 Huw Davies
4  *
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.
9  *
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.
14  *
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
18  */
19
20 #include <stdarg.h>
21
22 #define COBJMACROS
23 #define NONAMELESSUNION
24 #define NONAMELESSSTRUCT
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winnls.h"
29 #include "ole2.h"
30 #include "msdadc.h"
31 #include "oledberr.h"
32
33 #include "oledb_private.h"
34
35 #include "wine/debug.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(oledb);
38
39 typedef struct
40 {
41     const struct IDataConvertVtbl *lpVtbl;
42     const struct IDCInfoVtbl *lpDCInfoVtbl;
43
44     LONG ref;
45
46     UINT version; /* Set by IDCInfo_SetInfo */
47 } convert;
48
49 static inline convert *impl_from_IDataConvert(IDataConvert *iface)
50 {
51     return (convert *)((char*)iface - FIELD_OFFSET(convert, lpVtbl));
52 }
53
54 static inline convert *impl_from_IDCInfo(IDCInfo *iface)
55 {
56     return (convert *)((char*)iface - FIELD_OFFSET(convert, lpDCInfoVtbl));
57 }
58
59 static HRESULT WINAPI convert_QueryInterface(IDataConvert* iface,
60                                              REFIID riid,
61                                              void **obj)
62 {
63     convert *This = impl_from_IDataConvert(iface);
64     TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), obj);
65
66     *obj = NULL;
67
68     if(IsEqualIID(riid, &IID_IUnknown) ||
69        IsEqualIID(riid, &IID_IDataConvert))
70     {
71         *obj = iface;
72     }
73     else if(IsEqualIID(riid, &IID_IDCInfo))
74     {
75         *obj = &This->lpDCInfoVtbl;
76     }
77     else
78     {
79         FIXME("interface %s not implemented\n", debugstr_guid(riid));
80         return E_NOINTERFACE;
81     }
82
83     IDataConvert_AddRef(iface);
84     return S_OK;
85 }
86
87
88 static ULONG WINAPI convert_AddRef(IDataConvert* iface)
89 {
90     convert *This = impl_from_IDataConvert(iface);
91     TRACE("(%p)\n", This);
92
93     return InterlockedIncrement(&This->ref);
94 }
95
96
97 static ULONG WINAPI convert_Release(IDataConvert* iface)
98 {
99     convert *This = impl_from_IDataConvert(iface);
100     LONG ref;
101
102     TRACE("(%p)\n", This);
103
104     ref = InterlockedDecrement(&This->ref);
105     if(ref == 0)
106     {
107         HeapFree(GetProcessHeap(), 0, This);
108     }
109
110     return ref;
111 }
112
113 static int get_length(DBTYPE type)
114 {
115     switch(type)
116     {
117     case DBTYPE_I1:
118     case DBTYPE_UI1:
119         return 1;
120     case DBTYPE_I2:
121     case DBTYPE_UI2:
122         return 2;
123     case DBTYPE_I4:
124     case DBTYPE_UI4:
125     case DBTYPE_R4:
126         return 4;
127     case DBTYPE_I8:
128     case DBTYPE_UI8:
129         return 8;
130     case DBTYPE_BSTR:
131         return sizeof(BSTR);
132     case DBTYPE_FILETIME:
133         return sizeof(FILETIME);
134     case DBTYPE_GUID:
135         return sizeof(GUID);
136     case DBTYPE_WSTR:
137     case DBTYPE_BYREF | DBTYPE_WSTR:
138         return 0;
139     default:
140         FIXME("Unhandled type %04x\n", type);
141         return 0;
142     }
143 }
144
145 static HRESULT WINAPI convert_DataConvert(IDataConvert* iface,
146                                           DBTYPE src_type, DBTYPE dst_type,
147                                           DBLENGTH src_len, DBLENGTH *dst_len,
148                                           void *src, void *dst,
149                                           DBLENGTH dst_max_len,
150                                           DBSTATUS src_status, DBSTATUS *dst_status,
151                                           BYTE precision, BYTE scale,
152                                           DBDATACONVERT flags)
153 {
154     convert *This = impl_from_IDataConvert(iface);
155     HRESULT hr;
156
157     TRACE("(%p)->(%d, %d, %d, %p, %p, %p, %d, %d, %p, %d, %d, %x)\n", This,
158           src_type, dst_type, src_len, dst_len, src, dst, dst_max_len,
159           src_status, dst_status, precision, scale, flags);
160
161     *dst_len = get_length(dst_type);
162     *dst_status = DBSTATUS_E_BADACCESSOR;
163
164     if(IDataConvert_CanConvert(iface, src_type, dst_type) != S_OK)
165     {
166         return DB_E_UNSUPPORTEDCONVERSION;
167     }
168
169     if(src_type == DBTYPE_STR)
170     {
171         BSTR b;
172         DWORD len;
173
174         if(flags & DBDATACONVERT_LENGTHFROMNTS)
175             len = MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0) - 1;
176         else
177             len = MultiByteToWideChar(CP_ACP, 0, src, src_len, NULL, 0);
178         b = SysAllocStringLen(NULL, len);
179         if(!b) return E_OUTOFMEMORY;
180         if(flags & DBDATACONVERT_LENGTHFROMNTS)
181             MultiByteToWideChar(CP_ACP, 0, src, -1, b, len + 1);
182         else
183             MultiByteToWideChar(CP_ACP, 0, src, src_len, b, len);
184
185         hr = IDataConvert_DataConvert(iface, DBTYPE_BSTR, dst_type, 0, dst_len,
186                                       &b, dst, dst_max_len, src_status, dst_status,
187                                       precision, scale, flags);
188
189         SysFreeString(b);
190         return hr;
191     }
192
193     if(src_type == DBTYPE_WSTR)
194     {
195         BSTR b;
196
197         if(flags & DBDATACONVERT_LENGTHFROMNTS)
198             b = SysAllocString(src);
199         else
200             b = SysAllocStringLen(src, src_len / 2);
201         if(!b) return E_OUTOFMEMORY;
202         hr = IDataConvert_DataConvert(iface, DBTYPE_BSTR, dst_type, 0, dst_len,
203                                       &b, dst, dst_max_len, src_status, dst_status,
204                                       precision, scale, flags);
205         SysFreeString(b);
206         return hr;
207     }
208
209     switch(dst_type)
210     {
211     case DBTYPE_I2:
212     {
213         signed short *d = dst;
214         switch(src_type)
215         {
216         case DBTYPE_EMPTY:       *d = 0; hr = S_OK;                              break;
217         case DBTYPE_I2:          *d = *(signed short*)src; hr = S_OK;            break;
218         case DBTYPE_I4:          hr = VarI2FromI4(*(signed int*)src, d);         break;
219         case DBTYPE_R4:          hr = VarI2FromR4(*(FLOAT*)src, d);              break;
220         case DBTYPE_R8:          hr = VarI2FromR8(*(double*)src, d);             break;
221         case DBTYPE_CY:          hr = VarI2FromCy(*(CY*)src, d);                 break;
222         case DBTYPE_DATE:        hr = VarI2FromDate(*(DATE*)src, d);             break;
223         case DBTYPE_BSTR:        hr = VarI2FromStr(*(WCHAR**)src, LOCALE_USER_DEFAULT, 0, d); break;
224         case DBTYPE_BOOL:        hr = VarI2FromBool(*(VARIANT_BOOL*)src, d);     break;
225         case DBTYPE_DECIMAL:     hr = VarI2FromDec((DECIMAL*)src, d);            break;
226         case DBTYPE_I1:          hr = VarI2FromI1(*(signed char*)src, d);        break;
227         case DBTYPE_UI1:         hr = VarI2FromUI1(*(BYTE*)src, d);              break;
228         case DBTYPE_UI2:         hr = VarI2FromUI2(*(WORD*)src, d);              break;
229         case DBTYPE_UI4:         hr = VarI2FromUI4(*(DWORD*)src, d);             break;
230         case DBTYPE_I8:          hr = VarI2FromI8(*(LONGLONG*)src, d);           break;
231         case DBTYPE_UI8:         hr = VarI2FromUI8(*(ULONGLONG*)src, d);         break;
232         default: FIXME("Unimplemented conversion %04x -> I2\n", src_type); return E_NOTIMPL;
233         }
234         break;
235     }
236
237     case DBTYPE_I4:
238     {
239         signed int *d = dst;
240         switch(src_type)
241         {
242         case DBTYPE_EMPTY:       *d = 0; hr = S_OK;                              break;
243         case DBTYPE_I2:          hr = VarI4FromI2(*(signed short*)src, d);       break;
244         case DBTYPE_I4:          *d = *(signed int*)src; hr = S_OK;              break;
245         case DBTYPE_R4:          hr = VarI4FromR4(*(FLOAT*)src, d);              break;
246         case DBTYPE_R8:          hr = VarI4FromR8(*(double*)src, d);             break;
247         case DBTYPE_CY:          hr = VarI4FromCy(*(CY*)src, d);                 break;
248         case DBTYPE_DATE:        hr = VarI4FromDate(*(DATE*)src, d);             break;
249         case DBTYPE_BSTR:        hr = VarI4FromStr(*(WCHAR**)src, LOCALE_USER_DEFAULT, 0, d); break;
250         case DBTYPE_BOOL:        hr = VarI4FromBool(*(VARIANT_BOOL*)src, d);     break;
251         case DBTYPE_DECIMAL:     hr = VarI4FromDec((DECIMAL*)src, d);            break;
252         case DBTYPE_I1:          hr = VarI4FromI1(*(signed char*)src, d);        break;
253         case DBTYPE_UI1:         hr = VarI4FromUI1(*(BYTE*)src, d);              break;
254         case DBTYPE_UI2:         hr = VarI4FromUI2(*(WORD*)src, d);              break;
255         case DBTYPE_UI4:         hr = VarI4FromUI4(*(DWORD*)src, d);             break;
256         case DBTYPE_I8:          hr = VarI4FromI8(*(LONGLONG*)src, d);           break;
257         case DBTYPE_UI8:         hr = VarI4FromUI8(*(ULONGLONG*)src, d);         break;
258         default: FIXME("Unimplemented conversion %04x -> I4\n", src_type); return E_NOTIMPL;
259         }
260         break;
261     }
262
263     case DBTYPE_R4:
264     {
265         FLOAT *d = dst;
266         switch(src_type)
267         {
268         case DBTYPE_EMPTY:       *d = 0; hr = S_OK;                              break;
269         case DBTYPE_I2:          hr = VarR4FromI2(*(signed short*)src, d);       break;
270         case DBTYPE_I4:          hr = VarR4FromI4(*(signed int*)src, d);         break;
271         case DBTYPE_R4:          *d = *(FLOAT*)src; hr = S_OK;                   break;
272         case DBTYPE_R8:          hr = VarR4FromR8(*(double*)src, d);             break;
273         case DBTYPE_CY:          hr = VarR4FromCy(*(CY*)src, d);                 break;
274         case DBTYPE_DATE:        hr = VarR4FromDate(*(DATE*)src, d);             break;
275         case DBTYPE_BSTR:        hr = VarR4FromStr(*(WCHAR**)src, LOCALE_USER_DEFAULT, 0, d); break;
276         case DBTYPE_BOOL:        hr = VarR4FromBool(*(VARIANT_BOOL*)src, d);     break;
277         case DBTYPE_DECIMAL:     hr = VarR4FromDec((DECIMAL*)src, d);            break;
278         case DBTYPE_I1:          hr = VarR4FromI1(*(signed char*)src, d);        break;
279         case DBTYPE_UI1:         hr = VarR4FromUI1(*(BYTE*)src, d);              break;
280         case DBTYPE_UI2:         hr = VarR4FromUI2(*(WORD*)src, d);              break;
281         case DBTYPE_UI4:         hr = VarR4FromUI4(*(DWORD*)src, d);             break;
282         case DBTYPE_I8:          hr = VarR4FromI8(*(LONGLONG*)src, d);           break;
283         case DBTYPE_UI8:         hr = VarR4FromUI8(*(ULONGLONG*)src, d);         break;
284         default: FIXME("Unimplemented conversion %04x -> R4\n", src_type); return E_NOTIMPL;
285         }
286         break;
287     }
288
289     case DBTYPE_BSTR:
290     {
291         BSTR *d = dst;
292         switch(src_type)
293         {
294         case DBTYPE_EMPTY:       *d = SysAllocStringLen(NULL, 0); hr = *d ? S_OK : E_OUTOFMEMORY;      break;
295         case DBTYPE_I2:          hr = VarBstrFromI2(*(signed short*)src, LOCALE_USER_DEFAULT, 0, d);   break;
296         case DBTYPE_I4:          hr = VarBstrFromI4(*(signed int*)src, LOCALE_USER_DEFAULT, 0, d);     break;
297         case DBTYPE_R4:          hr = VarBstrFromR4(*(FLOAT*)src, LOCALE_USER_DEFAULT, 0, d);          break;
298         case DBTYPE_R8:          hr = VarBstrFromR8(*(double*)src, LOCALE_USER_DEFAULT, 0, d);         break;
299         case DBTYPE_CY:          hr = VarBstrFromCy(*(CY*)src, LOCALE_USER_DEFAULT, 0, d);             break;
300         case DBTYPE_DATE:        hr = VarBstrFromDate(*(DATE*)src, LOCALE_USER_DEFAULT, 0, d);         break;
301         case DBTYPE_BSTR:        *d = SysAllocStringLen(*(BSTR*)src, SysStringLen(*(BSTR*)src)); hr = *d ? S_OK : E_OUTOFMEMORY;     break;
302         case DBTYPE_BOOL:        hr = VarBstrFromBool(*(VARIANT_BOOL*)src, LOCALE_USER_DEFAULT, 0, d); break;
303         case DBTYPE_DECIMAL:     hr = VarBstrFromDec((DECIMAL*)src, LOCALE_USER_DEFAULT, 0, d);        break;
304         case DBTYPE_I1:          hr = VarBstrFromI1(*(signed char*)src, LOCALE_USER_DEFAULT, 0, d);    break;
305         case DBTYPE_UI1:         hr = VarBstrFromUI1(*(BYTE*)src, LOCALE_USER_DEFAULT, 0, d);          break;
306         case DBTYPE_UI2:         hr = VarBstrFromUI2(*(WORD*)src, LOCALE_USER_DEFAULT, 0, d);          break;
307         case DBTYPE_UI4:         hr = VarBstrFromUI4(*(DWORD*)src, LOCALE_USER_DEFAULT, 0, d);         break;
308         case DBTYPE_I8:          hr = VarBstrFromI8(*(LONGLONG*)src, LOCALE_USER_DEFAULT, 0, d);       break;
309         case DBTYPE_UI8:         hr = VarBstrFromUI8(*(ULONGLONG*)src, LOCALE_USER_DEFAULT, 0, d);     break;
310         default: FIXME("Unimplemented conversion %04x -> BSTR\n", src_type); return E_NOTIMPL;
311         }
312         break;
313     }
314
315     case DBTYPE_UI1:
316     {
317         BYTE *d = dst;
318         switch(src_type)
319         {
320         case DBTYPE_EMPTY:       *d = 0; hr = S_OK;                              break;
321         case DBTYPE_I2:          hr = VarUI1FromI2(*(signed short*)src, d);      break;
322         case DBTYPE_I4:          hr = VarUI1FromI4(*(signed int*)src, d);        break;
323         case DBTYPE_R4:          hr = VarUI1FromR4(*(FLOAT*)src, d);             break;
324         case DBTYPE_R8:          hr = VarUI1FromR8(*(double*)src, d);            break;
325         case DBTYPE_CY:          hr = VarUI1FromCy(*(CY*)src, d);                break;
326         case DBTYPE_DATE:        hr = VarUI1FromDate(*(DATE*)src, d);            break;
327         case DBTYPE_BSTR:        hr = VarUI1FromStr(*(WCHAR**)src, LOCALE_USER_DEFAULT, 0, d); break;
328         case DBTYPE_BOOL:        hr = VarUI1FromBool(*(VARIANT_BOOL*)src, d);    break;
329         case DBTYPE_DECIMAL:     hr = VarUI1FromDec((DECIMAL*)src, d);           break;
330         case DBTYPE_I1:          hr = VarUI1FromI1(*(signed char*)src, d);       break;
331         case DBTYPE_UI1:         *d = *(BYTE*)src; hr = S_OK;                    break;
332         case DBTYPE_UI2:         hr = VarUI1FromUI2(*(WORD*)src, d);             break;
333         case DBTYPE_UI4:         hr = VarUI1FromUI4(*(DWORD*)src, d);            break;
334         case DBTYPE_I8:          hr = VarUI1FromI8(*(LONGLONG*)src, d);          break;
335         case DBTYPE_UI8:         hr = VarUI1FromUI8(*(ULONGLONG*)src, d);        break;
336         default: FIXME("Unimplemented conversion %04x -> UI1\n", src_type); return E_NOTIMPL;
337         }
338         break;
339     }
340
341     case DBTYPE_UI4:
342     {
343         DWORD *d = dst;
344         switch(src_type)
345         {
346         case DBTYPE_EMPTY:       *d = 0; hr = S_OK;                              break;
347         case DBTYPE_I2:          hr = VarUI4FromI2(*(signed short*)src, d);      break;
348         case DBTYPE_I4:          hr = VarUI4FromI4(*(signed int*)src, d);        break;
349         case DBTYPE_R4:          hr = VarUI4FromR4(*(FLOAT*)src, d);             break;
350         case DBTYPE_R8:          hr = VarUI4FromR8(*(double*)src, d);            break;
351         case DBTYPE_CY:          hr = VarUI4FromCy(*(CY*)src, d);                break;
352         case DBTYPE_DATE:        hr = VarUI4FromDate(*(DATE*)src, d);            break;
353         case DBTYPE_BSTR:        hr = VarUI4FromStr(*(WCHAR**)src, LOCALE_USER_DEFAULT, 0, d); break;
354         case DBTYPE_BOOL:        hr = VarUI4FromBool(*(VARIANT_BOOL*)src, d);    break;
355         case DBTYPE_DECIMAL:     hr = VarUI4FromDec((DECIMAL*)src, d);           break;
356         case DBTYPE_I1:          hr = VarUI4FromI1(*(signed char*)src, d);       break;
357         case DBTYPE_UI1:         hr = VarUI4FromUI1(*(BYTE*)src, d);             break;
358         case DBTYPE_UI2:         hr = VarUI4FromUI2(*(WORD*)src, d);             break;
359         case DBTYPE_UI4:         *d = *(DWORD*)src; hr = S_OK;                   break;
360         case DBTYPE_I8:          hr = VarUI4FromI8(*(LONGLONG*)src, d);          break;
361         case DBTYPE_UI8:         hr = VarUI4FromUI8(*(ULONGLONG*)src, d);        break;
362         default: FIXME("Unimplemented conversion %04x -> UI4\n", src_type); return E_NOTIMPL;
363         }
364         break;
365     }
366
367     case DBTYPE_FILETIME:
368     {
369         FILETIME *d = dst;
370         switch(src_type)
371         {
372         case DBTYPE_EMPTY:       d->dwLowDateTime = d->dwHighDateTime = 0; hr = S_OK;    break;
373         case DBTYPE_FILETIME:    *d = *(FILETIME*)src; hr = S_OK;                        break;
374         default: FIXME("Unimplemented conversion %04x -> FILETIME\n", src_type); return E_NOTIMPL;
375         }
376         break;
377     }
378
379     case DBTYPE_GUID:
380     {
381         GUID *d = dst;
382         switch(src_type)
383         {
384         case DBTYPE_EMPTY:       *d = GUID_NULL; hr = S_OK; break;
385         case DBTYPE_GUID:        *d = *(GUID*)src; hr = S_OK; break;
386         default: FIXME("Unimplemented conversion %04x -> GUID\n", src_type); return E_NOTIMPL;
387         }
388         break;
389     }
390
391     case DBTYPE_WSTR:
392     {
393         BSTR b;
394         DBLENGTH bstr_len;
395         INT bytes_to_copy;
396         hr = IDataConvert_DataConvert(iface, src_type, DBTYPE_BSTR, src_len, &bstr_len,
397                                       src, &b, sizeof(BSTR), src_status, dst_status,
398                                       precision, scale, flags);
399         if(hr != S_OK) return hr;
400         bstr_len = SysStringLen(b);
401         *dst_len = bstr_len * sizeof(WCHAR); /* Doesn't include size for '\0' */
402         *dst_status = DBSTATUS_S_OK;
403         bytes_to_copy = min(*dst_len + sizeof(WCHAR), dst_max_len);
404         if(dst)
405         {
406             if(bytes_to_copy >= sizeof(WCHAR))
407             {
408                 memcpy(dst, b, bytes_to_copy - sizeof(WCHAR));
409                 *((WCHAR*)dst + bytes_to_copy / sizeof(WCHAR) - 1) = 0;
410                 if(bytes_to_copy < *dst_len + sizeof(WCHAR))
411                     *dst_status = DBSTATUS_S_TRUNCATED;
412             }
413             else
414             {
415                 *dst_status = DBSTATUS_E_DATAOVERFLOW;
416                 hr = DB_E_ERRORSOCCURRED;
417             }
418         }
419         SysFreeString(b);
420         return hr;
421     }
422
423     case DBTYPE_BYREF | DBTYPE_WSTR:
424     {
425         BSTR b;
426         WCHAR **d = dst;
427         DBLENGTH bstr_len;
428         hr = IDataConvert_DataConvert(iface, src_type, DBTYPE_BSTR, src_len, &bstr_len,
429                                       src, &b, sizeof(BSTR), src_status, dst_status,
430                                       precision, scale, flags);
431         if(hr != S_OK) return hr;
432
433         bstr_len = SysStringLen(b) * sizeof(WCHAR);
434         *dst_len = bstr_len; /* Doesn't include size for '\0' */
435
436         *d = CoTaskMemAlloc(bstr_len + sizeof(WCHAR));
437         if(*d) memcpy(*d, b, bstr_len + sizeof(WCHAR));
438         else hr = E_OUTOFMEMORY;
439         SysFreeString(b);
440         return hr;
441     }
442
443     default:
444         FIXME("Unimplemented conversion %04x -> %04x\n", src_type, dst_type);
445         return E_NOTIMPL;
446
447     }
448
449     if(hr == DISP_E_OVERFLOW)
450     {
451         *dst_status = DBSTATUS_E_DATAOVERFLOW;
452         hr = DB_E_ERRORSOCCURRED;
453     }
454     else if(hr == S_OK)
455         *dst_status = DBSTATUS_S_OK;
456
457     return hr;
458 }
459
460 static inline WORD get_dbtype_class(DBTYPE type)
461 {
462     switch(type)
463     {
464     case DBTYPE_I2:
465     case DBTYPE_R4:
466     case DBTYPE_R8:
467     case DBTYPE_I1:
468     case DBTYPE_UI1:
469     case DBTYPE_UI2:
470         return DBTYPE_I2;
471
472     case DBTYPE_I4:
473     case DBTYPE_UI4:
474         return DBTYPE_I4;
475
476     case DBTYPE_I8:
477     case DBTYPE_UI8:
478         return DBTYPE_I8;
479
480     case DBTYPE_BSTR:
481     case DBTYPE_STR:
482     case DBTYPE_WSTR:
483         return DBTYPE_BSTR;
484
485     case DBTYPE_DBDATE:
486     case DBTYPE_DBTIME:
487     case DBTYPE_DBTIMESTAMP:
488         return DBTYPE_DBDATE;
489     }
490     return type;
491 }
492
493 /* Many src types will convert to this group of dst types */
494 static inline BOOL common_class(WORD dst_class)
495 {
496     switch(dst_class)
497     {
498     case DBTYPE_EMPTY:
499     case DBTYPE_NULL:
500     case DBTYPE_I2:
501     case DBTYPE_I4:
502     case DBTYPE_BSTR:
503     case DBTYPE_BOOL:
504     case DBTYPE_VARIANT:
505     case DBTYPE_I8:
506     case DBTYPE_CY:
507     case DBTYPE_DECIMAL:
508     case DBTYPE_NUMERIC:
509         return TRUE;
510     }
511     return FALSE;
512 }
513
514 static inline BOOL array_type(DBTYPE type)
515 {
516     return (type >= DBTYPE_I2 && type <= DBTYPE_UI4);
517 }
518
519 static HRESULT WINAPI convert_CanConvert(IDataConvert* iface,
520                                          DBTYPE src_type, DBTYPE dst_type)
521 {
522     convert *This = impl_from_IDataConvert(iface);
523     DBTYPE src_base_type = src_type & 0x1ff;
524     DBTYPE dst_base_type = dst_type & 0x1ff;
525     WORD dst_class = get_dbtype_class(dst_base_type);
526
527     TRACE("(%p)->(%d, %d)\n", This, src_type, dst_type);
528
529     if(src_type & DBTYPE_VECTOR || dst_type & DBTYPE_VECTOR) return S_FALSE;
530
531     if(src_type & DBTYPE_ARRAY)
532     {
533         if(!array_type(src_base_type)) return S_FALSE;
534         if(dst_type & DBTYPE_ARRAY)
535         {
536             if(src_type == dst_type) return S_OK;
537             return S_FALSE;
538         }
539         if(dst_type == DBTYPE_VARIANT) return S_OK;
540         return S_FALSE;
541     }
542
543     if(dst_type & DBTYPE_ARRAY)
544     {
545         if(!array_type(dst_base_type)) return S_FALSE;
546         if(src_type == DBTYPE_IDISPATCH || src_type == DBTYPE_VARIANT) return S_OK;
547         return S_FALSE;
548     }
549
550     if(dst_type & DBTYPE_BYREF)
551         if(dst_base_type != DBTYPE_BYTES && dst_base_type != DBTYPE_STR && dst_base_type != DBTYPE_WSTR)
552             return S_FALSE;
553
554     switch(get_dbtype_class(src_base_type))
555     {
556     case DBTYPE_EMPTY:
557         if(common_class(dst_class)) return S_OK;
558         switch(dst_class)
559         {
560         case DBTYPE_DATE:
561         case DBTYPE_GUID:
562         case DBTYPE_FILETIME:
563             return S_OK;
564         default:
565             if(dst_base_type == DBTYPE_DBTIMESTAMP) return S_OK;
566             return S_FALSE;
567         }
568
569     case DBTYPE_NULL:
570         switch(dst_base_type)
571         {
572         case DBTYPE_NULL:
573         case DBTYPE_VARIANT:
574         case DBTYPE_FILETIME: return S_OK;
575         default: return S_FALSE;
576         }
577
578     case DBTYPE_I4:
579         if(dst_base_type == DBTYPE_BYTES) return S_OK;
580         /* fall through */
581     case DBTYPE_I2:
582         if(dst_base_type == DBTYPE_DATE) return S_OK;
583         /* fall through */
584     case DBTYPE_DECIMAL:
585         if(common_class(dst_class)) return S_OK;
586         if(dst_class == DBTYPE_DBDATE) return S_OK;
587         return S_FALSE;
588
589     case DBTYPE_BOOL:
590         if(dst_base_type == DBTYPE_DATE) return S_OK;
591     case DBTYPE_NUMERIC:
592     case DBTYPE_CY:
593         if(common_class(dst_class)) return S_OK;
594         return S_FALSE;
595
596     case DBTYPE_I8:
597         if(common_class(dst_class)) return S_OK;
598         switch(dst_base_type)
599         {
600         case DBTYPE_BYTES:
601         case DBTYPE_FILETIME: return S_OK;
602         default: return S_FALSE;
603         }
604
605     case DBTYPE_DATE:
606         switch(dst_class)
607         {
608         case DBTYPE_EMPTY:
609         case DBTYPE_NULL:
610         case DBTYPE_I2:
611         case DBTYPE_I4:
612         case DBTYPE_BSTR:
613         case DBTYPE_BOOL:
614         case DBTYPE_VARIANT:
615         case DBTYPE_I8:
616         case DBTYPE_DATE:
617         case DBTYPE_DBDATE:
618         case DBTYPE_FILETIME:
619             return S_OK;
620         default: return S_FALSE;
621         }
622
623     case DBTYPE_IDISPATCH:
624     case DBTYPE_VARIANT:
625         switch(dst_base_type)
626         {
627         case DBTYPE_IDISPATCH:
628         case DBTYPE_ERROR:
629         case DBTYPE_IUNKNOWN:
630             return S_OK;
631         }
632         /* fall through */
633     case DBTYPE_BSTR:
634         if(common_class(dst_class)) return S_OK;
635         switch(dst_class)
636         {
637         case DBTYPE_DATE:
638         case DBTYPE_GUID:
639         case DBTYPE_BYTES:
640         case DBTYPE_DBDATE:
641         case DBTYPE_FILETIME:
642             return S_OK;
643         default: return S_FALSE;
644         }
645
646     case DBTYPE_ERROR:
647         switch(dst_base_type)
648         {
649         case DBTYPE_BSTR:
650         case DBTYPE_ERROR:
651         case DBTYPE_VARIANT:
652         case DBTYPE_WSTR:
653             return S_OK;
654         default: return S_FALSE;
655         }
656
657     case DBTYPE_IUNKNOWN:
658         switch(dst_base_type)
659         {
660         case DBTYPE_EMPTY:
661         case DBTYPE_NULL:
662         case DBTYPE_IDISPATCH:
663         case DBTYPE_VARIANT:
664         case DBTYPE_IUNKNOWN:
665             return S_OK;
666         default: return S_FALSE;
667         }
668
669     case DBTYPE_BYTES:
670         if(dst_class == DBTYPE_I4 || dst_class == DBTYPE_I8) return S_OK;
671         /* fall through */
672     case DBTYPE_GUID:
673         switch(dst_class)
674         {
675         case DBTYPE_EMPTY:
676         case DBTYPE_NULL:
677         case DBTYPE_BSTR:
678         case DBTYPE_VARIANT:
679         case DBTYPE_GUID:
680         case DBTYPE_BYTES:
681             return S_OK;
682         default: return S_FALSE;
683         }
684
685     case DBTYPE_FILETIME:
686         if(dst_class == DBTYPE_I8) return S_OK;
687         /* fall through */
688     case DBTYPE_DBDATE:
689         switch(dst_class)
690         {
691         case DBTYPE_EMPTY:
692         case DBTYPE_NULL:
693         case DBTYPE_DATE:
694         case DBTYPE_BSTR:
695         case DBTYPE_VARIANT:
696         case DBTYPE_DBDATE:
697         case DBTYPE_FILETIME:
698             return S_OK;
699         default: return S_FALSE;
700         }
701
702     }
703     return S_FALSE;
704 }
705
706 static HRESULT WINAPI convert_GetConversionSize(IDataConvert* iface,
707                                                 DBTYPE wSrcType, DBTYPE wDstType,
708                                                 DBLENGTH *pcbSrcLength, DBLENGTH *pcbDstLength,
709                                                 void *pSrc)
710 {
711     convert *This = impl_from_IDataConvert(iface);
712     FIXME("(%p)->(%d, %d, %p, %p, %p): stub\n", This, wSrcType, wDstType, pcbSrcLength, pcbDstLength, pSrc);
713
714     return E_NOTIMPL;
715 }
716
717 static const struct IDataConvertVtbl convert_vtbl =
718 {
719     convert_QueryInterface,
720     convert_AddRef,
721     convert_Release,
722     convert_DataConvert,
723     convert_CanConvert,
724     convert_GetConversionSize
725 };
726
727 static HRESULT WINAPI dcinfo_QueryInterface(IDCInfo* iface, REFIID riid, void **obj)
728 {
729     convert *This = impl_from_IDCInfo(iface);
730
731     return IDataConvert_QueryInterface((IDataConvert *)This, riid, obj);
732 }
733
734 static ULONG WINAPI dcinfo_AddRef(IDCInfo* iface)
735 {
736     convert *This = impl_from_IDCInfo(iface);
737
738     return IDataConvert_AddRef((IDataConvert *)This);
739 }
740
741 static ULONG WINAPI dcinfo_Release(IDCInfo* iface)
742 {
743     convert *This = impl_from_IDCInfo(iface);
744
745     return IDataConvert_Release((IDataConvert *)This);
746 }
747
748 static HRESULT WINAPI dcinfo_GetInfo(IDCInfo *iface, ULONG num, DCINFOTYPE types[], DCINFO **info_ptr)
749 {
750     convert *This = impl_from_IDCInfo(iface);
751     ULONG i;
752     DCINFO *infos;
753
754     TRACE("(%p)->(%d, %p, %p)\n", This, num, types, info_ptr);
755
756     *info_ptr = infos = CoTaskMemAlloc(num * sizeof(*infos));
757     if(!infos) return E_OUTOFMEMORY;
758
759     for(i = 0; i < num; i++)
760     {
761         infos[i].eInfoType = types[i];
762         VariantInit(&infos[i].vData);
763
764         switch(types[i])
765         {
766         case DCINFOTYPE_VERSION:
767             V_VT(&infos[i].vData) = VT_UI4;
768             V_UI4(&infos[i].vData) = This->version;
769             break;
770         }
771     }
772
773     return S_OK;
774 }
775
776 static HRESULT WINAPI dcinfo_SetInfo(IDCInfo* iface, ULONG num, DCINFO info[])
777 {
778     convert *This = impl_from_IDCInfo(iface);
779     ULONG i;
780     HRESULT hr = S_OK;
781
782     TRACE("(%p)->(%d, %p)\n", This, num, info);
783
784     for(i = 0; i < num; i++)
785     {
786         switch(info[i].eInfoType)
787         {
788         case DCINFOTYPE_VERSION:
789             if(V_VT(&info[i].vData) != VT_UI4)
790             {
791                 FIXME("VERSION with vt %x\n", V_VT(&info[i].vData));
792                 hr = DB_S_ERRORSOCCURRED;
793                 break;
794             }
795             This->version = V_UI4(&info[i].vData);
796             break;
797
798         default:
799             FIXME("Unhandled info type %d (vt %x)\n", info[i].eInfoType, V_VT(&info[i].vData));
800         }
801     }
802     return hr;
803 }
804
805 static const struct IDCInfoVtbl dcinfo_vtbl =
806 {
807     dcinfo_QueryInterface,
808     dcinfo_AddRef,
809     dcinfo_Release,
810     dcinfo_GetInfo,
811     dcinfo_SetInfo
812 };
813
814 HRESULT create_oledb_convert(IUnknown *outer, void **obj)
815 {
816     convert *This;
817
818     TRACE("(%p, %p)\n", outer, obj);
819
820     *obj = NULL;
821
822     if(outer) return CLASS_E_NOAGGREGATION;
823
824     This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
825     if(!This) return E_OUTOFMEMORY;
826
827     This->lpVtbl = &convert_vtbl;
828     This->lpDCInfoVtbl = &dcinfo_vtbl;
829     This->ref = 1;
830     This->version = 0x110;
831
832     *obj = &This->lpVtbl;
833
834     return S_OK;
835 }