Release 1.5.29.
[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     IDataConvert IDataConvert_iface;
42     IDCInfo IDCInfo_iface;
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 CONTAINING_RECORD(iface, convert, IDataConvert_iface);
52 }
53
54 static inline convert *impl_from_IDCInfo(IDCInfo *iface)
55 {
56     return CONTAINING_RECORD(iface, convert, IDCInfo_iface);
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->IDCInfo_iface;
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_BOOL:
124         return sizeof(VARIANT_BOOL);
125     case DBTYPE_I4:
126     case DBTYPE_UI4:
127     case DBTYPE_R4:
128         return 4;
129     case DBTYPE_I8:
130     case DBTYPE_UI8:
131     case DBTYPE_R8:
132     case DBTYPE_DATE:
133         return 8;
134     case DBTYPE_DBTIMESTAMP:
135         return sizeof(DBTIMESTAMP);
136     case DBTYPE_CY:
137         return sizeof(CY);
138     case DBTYPE_BSTR:
139         return sizeof(BSTR);
140     case DBTYPE_FILETIME:
141         return sizeof(FILETIME);
142     case DBTYPE_GUID:
143         return sizeof(GUID);
144     case DBTYPE_WSTR:
145     case DBTYPE_STR:
146     case DBTYPE_BYREF | DBTYPE_WSTR:
147         return 0;
148     case DBTYPE_VARIANT:
149         return sizeof(VARIANT);
150     default:
151         FIXME("Unhandled type %04x\n", type);
152         return 0;
153     }
154 }
155
156 static HRESULT WINAPI convert_DataConvert(IDataConvert* iface,
157                                           DBTYPE src_type, DBTYPE dst_type,
158                                           DBLENGTH src_len, DBLENGTH *dst_len,
159                                           void *src, void *dst,
160                                           DBLENGTH dst_max_len,
161                                           DBSTATUS src_status, DBSTATUS *dst_status,
162                                           BYTE precision, BYTE scale,
163                                           DBDATACONVERT flags)
164 {
165     convert *This = impl_from_IDataConvert(iface);
166     DBLENGTH dst_len_loc;
167     DBSTATUS dst_status_loc;
168     VARIANT tmp;
169     HRESULT hr;
170
171     TRACE("(%p)->(%d, %d, %ld, %p, %p, %p, %ld, %d, %p, %d, %d, %x)\n", This,
172           src_type, dst_type, src_len, dst_len, src, dst, dst_max_len,
173           src_status, dst_status, precision, scale, flags);
174
175     if (!dst_len) dst_len = &dst_len_loc;
176     if (!dst_status) dst_status = &dst_status_loc;
177
178     *dst_status = DBSTATUS_E_BADACCESSOR;
179
180     if(IDataConvert_CanConvert(iface, src_type, dst_type) != S_OK)
181     {
182         return DB_E_UNSUPPORTEDCONVERSION;
183     }
184
185     if(src_type == DBTYPE_STR)
186     {
187         BSTR b;
188         DWORD len;
189
190         if(flags & DBDATACONVERT_LENGTHFROMNTS)
191             len = MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0) - 1;
192         else
193             len = MultiByteToWideChar(CP_ACP, 0, src, src_len, NULL, 0);
194         b = SysAllocStringLen(NULL, len);
195         if(!b) return E_OUTOFMEMORY;
196         if(flags & DBDATACONVERT_LENGTHFROMNTS)
197             MultiByteToWideChar(CP_ACP, 0, src, -1, b, len + 1);
198         else
199             MultiByteToWideChar(CP_ACP, 0, src, src_len, b, len);
200
201         hr = IDataConvert_DataConvert(iface, DBTYPE_BSTR, dst_type, 0, dst_len,
202                                       &b, dst, dst_max_len, src_status, dst_status,
203                                       precision, scale, flags);
204
205         SysFreeString(b);
206         return hr;
207     }
208
209     if(src_type == DBTYPE_WSTR)
210     {
211         BSTR b;
212
213         if(flags & DBDATACONVERT_LENGTHFROMNTS)
214             b = SysAllocString(src);
215         else
216             b = SysAllocStringLen(src, src_len / 2);
217         if(!b) return E_OUTOFMEMORY;
218         hr = IDataConvert_DataConvert(iface, DBTYPE_BSTR, dst_type, 0, dst_len,
219                                       &b, dst, dst_max_len, src_status, dst_status,
220                                       precision, scale, flags);
221         SysFreeString(b);
222         return hr;
223     }
224
225     switch(dst_type)
226     {
227     case DBTYPE_I2:
228     {
229         signed short *d = dst;
230         switch(src_type)
231         {
232         case DBTYPE_EMPTY:       *d = 0; hr = S_OK;                              break;
233         case DBTYPE_I2:          *d = *(signed short*)src; hr = S_OK;            break;
234         case DBTYPE_I4:          hr = VarI2FromI4(*(signed int*)src, d);         break;
235         case DBTYPE_R4:          hr = VarI2FromR4(*(FLOAT*)src, d);              break;
236         case DBTYPE_R8:          hr = VarI2FromR8(*(double*)src, d);             break;
237         case DBTYPE_CY:          hr = VarI2FromCy(*(CY*)src, d);                 break;
238         case DBTYPE_DATE:        hr = VarI2FromDate(*(DATE*)src, d);             break;
239         case DBTYPE_BSTR:        hr = VarI2FromStr(*(WCHAR**)src, LOCALE_USER_DEFAULT, 0, d); break;
240         case DBTYPE_BOOL:        hr = VarI2FromBool(*(VARIANT_BOOL*)src, d);     break;
241         case DBTYPE_DECIMAL:     hr = VarI2FromDec((DECIMAL*)src, d);            break;
242         case DBTYPE_I1:          hr = VarI2FromI1(*(signed char*)src, d);        break;
243         case DBTYPE_UI1:         hr = VarI2FromUI1(*(BYTE*)src, d);              break;
244         case DBTYPE_UI2:         hr = VarI2FromUI2(*(WORD*)src, d);              break;
245         case DBTYPE_UI4:         hr = VarI2FromUI4(*(DWORD*)src, d);             break;
246         case DBTYPE_I8:          hr = VarI2FromI8(*(LONGLONG*)src, d);           break;
247         case DBTYPE_UI8:         hr = VarI2FromUI8(*(ULONGLONG*)src, d);         break;
248         case DBTYPE_VARIANT:
249             VariantInit(&tmp);
250             if ((hr = VariantChangeType(&tmp, (VARIANT*)src, 0, VT_I2)) == S_OK)
251                 *d = V_I2(&tmp);
252             break;
253         default: FIXME("Unimplemented conversion %04x -> I2\n", src_type); return E_NOTIMPL;
254         }
255         break;
256     }
257
258     case DBTYPE_I4:
259     {
260         signed int *d = dst;
261         switch(src_type)
262         {
263         case DBTYPE_EMPTY:       *d = 0; hr = S_OK;                              break;
264         case DBTYPE_I2:          hr = VarI4FromI2(*(signed short*)src, d);       break;
265         case DBTYPE_I4:          *d = *(signed int*)src; hr = S_OK;              break;
266         case DBTYPE_R4:          hr = VarI4FromR4(*(FLOAT*)src, d);              break;
267         case DBTYPE_R8:          hr = VarI4FromR8(*(double*)src, d);             break;
268         case DBTYPE_CY:          hr = VarI4FromCy(*(CY*)src, d);                 break;
269         case DBTYPE_DATE:        hr = VarI4FromDate(*(DATE*)src, d);             break;
270         case DBTYPE_BSTR:        hr = VarI4FromStr(*(WCHAR**)src, LOCALE_USER_DEFAULT, 0, d); break;
271         case DBTYPE_BOOL:        hr = VarI4FromBool(*(VARIANT_BOOL*)src, d);     break;
272         case DBTYPE_DECIMAL:     hr = VarI4FromDec((DECIMAL*)src, d);            break;
273         case DBTYPE_I1:          hr = VarI4FromI1(*(signed char*)src, d);        break;
274         case DBTYPE_UI1:         hr = VarI4FromUI1(*(BYTE*)src, d);              break;
275         case DBTYPE_UI2:         hr = VarI4FromUI2(*(WORD*)src, d);              break;
276         case DBTYPE_UI4:         hr = VarI4FromUI4(*(DWORD*)src, d);             break;
277         case DBTYPE_I8:          hr = VarI4FromI8(*(LONGLONG*)src, d);           break;
278         case DBTYPE_UI8:         hr = VarI4FromUI8(*(ULONGLONG*)src, d);         break;
279         case DBTYPE_VARIANT:
280             VariantInit(&tmp);
281             if ((hr = VariantChangeType(&tmp, (VARIANT*)src, 0, VT_I4)) == S_OK)
282                 *d = V_I4(&tmp);
283             break;
284         default: FIXME("Unimplemented conversion %04x -> I4\n", src_type); return E_NOTIMPL;
285         }
286         break;
287     }
288
289     case DBTYPE_I8:
290     {
291         LONGLONG *d = dst;
292         switch(src_type)
293         {
294         case DBTYPE_BSTR:        hr = VarI8FromStr(*(WCHAR**)src, LOCALE_USER_DEFAULT, 0, d); break;
295         case DBTYPE_I8:          *d = *(LONGLONG*)src; hr = S_OK;              break;
296         default: FIXME("Unimplemented conversion %04x -> I8\n", src_type); return E_NOTIMPL;
297         }
298         break;
299     }
300
301     case DBTYPE_R4:
302     {
303         FLOAT *d = dst;
304         switch(src_type)
305         {
306         case DBTYPE_EMPTY:       *d = 0; hr = S_OK;                              break;
307         case DBTYPE_I2:          hr = VarR4FromI2(*(signed short*)src, d);       break;
308         case DBTYPE_I4:          hr = VarR4FromI4(*(signed int*)src, d);         break;
309         case DBTYPE_R4:          *d = *(FLOAT*)src; hr = S_OK;                   break;
310         case DBTYPE_R8:          hr = VarR4FromR8(*(double*)src, d);             break;
311         case DBTYPE_CY:          hr = VarR4FromCy(*(CY*)src, d);                 break;
312         case DBTYPE_DATE:        hr = VarR4FromDate(*(DATE*)src, d);             break;
313         case DBTYPE_BSTR:        hr = VarR4FromStr(*(WCHAR**)src, LOCALE_USER_DEFAULT, 0, d); break;
314         case DBTYPE_BOOL:        hr = VarR4FromBool(*(VARIANT_BOOL*)src, d);     break;
315         case DBTYPE_DECIMAL:     hr = VarR4FromDec((DECIMAL*)src, d);            break;
316         case DBTYPE_I1:          hr = VarR4FromI1(*(signed char*)src, d);        break;
317         case DBTYPE_UI1:         hr = VarR4FromUI1(*(BYTE*)src, d);              break;
318         case DBTYPE_UI2:         hr = VarR4FromUI2(*(WORD*)src, d);              break;
319         case DBTYPE_UI4:         hr = VarR4FromUI4(*(DWORD*)src, d);             break;
320         case DBTYPE_I8:          hr = VarR4FromI8(*(LONGLONG*)src, d);           break;
321         case DBTYPE_UI8:         hr = VarR4FromUI8(*(ULONGLONG*)src, d);         break;
322         default: FIXME("Unimplemented conversion %04x -> R4\n", src_type); return E_NOTIMPL;
323         }
324         break;
325     }
326     case DBTYPE_R8:
327     {
328         DOUBLE *d=dst;
329         switch (src_type)
330         {
331         case DBTYPE_EMPTY:      *d = 0; hr = S_OK;                               break;
332         case DBTYPE_I1:          hr = VarR8FromI1(*(signed char*)src, d);        break;
333         case DBTYPE_I2:          hr = VarR8FromI2(*(signed short*)src, d);       break;
334         case DBTYPE_I4:          hr = VarR8FromI4(*(signed int*)src, d);         break;
335         case DBTYPE_I8:          hr = VarR8FromI8(*(LONGLONG*)src, d);           break;
336         case DBTYPE_UI1:         hr = VarR8FromUI1(*(BYTE*)src, d);              break;
337         case DBTYPE_UI2:         hr = VarR8FromUI2(*(WORD*)src, d);              break;
338         case DBTYPE_UI4:         hr = VarR8FromUI4(*(DWORD*)src, d);             break;
339         case DBTYPE_UI8:         hr = VarR8FromUI8(*(ULONGLONG*)src, d);         break;
340         case DBTYPE_R4:          hr = VarR8FromR4(*(FLOAT*)src, d);              break;
341         case DBTYPE_R8:          *d = *(DOUBLE*)src; hr = S_OK;                  break;
342         case DBTYPE_CY:          hr = VarR8FromCy(*(CY*)src, d);                 break;
343         case DBTYPE_DATE:        hr = VarR8FromDate(*(DATE*)src, d);             break;
344         case DBTYPE_BSTR:        hr = VarR8FromStr(*(WCHAR**)src, LOCALE_USER_DEFAULT, 0, d); break;
345         case DBTYPE_BOOL:        hr = VarR8FromBool(*(VARIANT_BOOL*)src, d);     break;
346         case DBTYPE_DECIMAL:     hr = VarR8FromDec((DECIMAL*)src, d);            break;
347         default: FIXME("Unimplemented conversion %04x -> R8\n", src_type); return E_NOTIMPL;
348         }
349         break;
350     }
351     case DBTYPE_BOOL:
352     {
353         VARIANT_BOOL *d=dst;
354         switch (src_type)
355         {
356         case DBTYPE_EMPTY:      *d = 0; hr = S_OK;                               break;
357         case DBTYPE_I1:          hr = VarBoolFromI1(*(signed char*)src, d);      break;
358         case DBTYPE_I2:          hr = VarBoolFromI2(*(signed short*)src, d);     break;
359         case DBTYPE_I4:          hr = VarBoolFromI4(*(signed int*)src, d);       break;
360         case DBTYPE_I8:          hr = VarBoolFromI8(*(LONGLONG*)src, d);         break;
361         case DBTYPE_UI1:         hr = VarBoolFromUI1(*(BYTE*)src, d);            break;
362         case DBTYPE_UI2:         hr = VarBoolFromUI2(*(WORD*)src, d);            break;
363         case DBTYPE_UI4:         hr = VarBoolFromUI4(*(DWORD*)src, d);           break;
364         case DBTYPE_UI8:         hr = VarBoolFromUI8(*(ULONGLONG*)src, d);       break;
365         case DBTYPE_R4:          hr = VarBoolFromR4(*(FLOAT*)src, d);            break;
366         case DBTYPE_R8:          hr = VarBoolFromR8(*(DOUBLE*)src, d);           break;
367         case DBTYPE_CY:          hr = VarBoolFromCy(*(CY*)src, d);               break;
368         case DBTYPE_DATE:        hr = VarBoolFromDate(*(DATE*)src, d);           break;
369         case DBTYPE_BSTR:        hr = VarBoolFromStr(*(WCHAR**)src, LOCALE_USER_DEFAULT, 0, d); break;
370         case DBTYPE_BOOL:        *d = *(VARIANT_BOOL*)src; hr = S_OK;            break;
371         case DBTYPE_DECIMAL:     hr = VarBoolFromDec((DECIMAL*)src, d);          break;
372         default: FIXME("Unimplemented conversion %04x -> BOOL\n", src_type); return E_NOTIMPL;
373         }
374         break;
375     }
376     case DBTYPE_DATE:
377     {
378         DATE *d=dst;
379         switch (src_type)
380         {
381         case DBTYPE_EMPTY:      *d = 0; hr = S_OK;                               break;
382         case DBTYPE_I1:          hr = VarDateFromI1(*(signed char*)src, d);      break;
383         case DBTYPE_I2:          hr = VarDateFromI2(*(signed short*)src, d);     break;
384         case DBTYPE_I4:          hr = VarDateFromI4(*(signed int*)src, d);       break;
385         case DBTYPE_I8:          hr = VarDateFromI8(*(LONGLONG*)src, d);         break;
386         case DBTYPE_UI1:         hr = VarDateFromUI1(*(BYTE*)src, d);            break;
387         case DBTYPE_UI2:         hr = VarDateFromUI2(*(WORD*)src, d);            break;
388         case DBTYPE_UI4:         hr = VarDateFromUI4(*(DWORD*)src, d);           break;
389         case DBTYPE_UI8:         hr = VarDateFromUI8(*(ULONGLONG*)src, d);       break;
390         case DBTYPE_R4:          hr = VarDateFromR4(*(FLOAT*)src, d);            break;
391         case DBTYPE_R8:          hr = VarDateFromR8(*(DOUBLE*)src, d);           break;
392         case DBTYPE_CY:          hr = VarDateFromCy(*(CY*)src, d);               break;
393         case DBTYPE_DATE:       *d = *(DATE*)src;      hr = S_OK;                break;
394         case DBTYPE_BSTR:        hr = VarDateFromStr(*(WCHAR**)src, LOCALE_USER_DEFAULT, 0, d); break;
395         case DBTYPE_BOOL:        hr = VarDateFromBool(*(VARIANT_BOOL*)src, d);   break;
396         case DBTYPE_DECIMAL:     hr = VarDateFromDec((DECIMAL*)src, d);          break;
397         case DBTYPE_DBTIMESTAMP:
398         {
399             SYSTEMTIME st;
400             DBTIMESTAMP *ts=(DBTIMESTAMP*)src;
401
402             st.wYear = ts->year;
403             st.wMonth = ts->month;
404             st.wDay = ts->day;
405             st.wHour = ts->hour;
406             st.wMinute = ts->minute;
407             st.wSecond = ts->second;
408             st.wMilliseconds = ts->fraction/1000000;
409             hr = (SystemTimeToVariantTime(&st, d) ? S_OK : E_FAIL);
410             break;
411         }
412         default: FIXME("Unimplemented conversion %04x -> DATE\n", src_type); return E_NOTIMPL;
413         }
414         break;
415     }
416     case DBTYPE_DBTIMESTAMP:
417     {
418         DBTIMESTAMP *d=dst;
419         switch (src_type)
420         {
421         case DBTYPE_EMPTY:       memset(d, 0, sizeof(DBTIMESTAMP));    hr = S_OK; break;
422         case DBTYPE_DBTIMESTAMP: memcpy(d, src, sizeof(DBTIMESTAMP));  hr = S_OK; break;
423         case DBTYPE_DATE:
424         {
425             SYSTEMTIME st;
426             hr = (VariantTimeToSystemTime(*(double*)src, &st) ? S_OK : E_FAIL);
427             d->year = st.wYear;
428             d->month = st.wMonth;
429             d->day = st.wDay;
430             d->hour = st.wHour;
431             d->minute = st.wMinute;
432             d->second = st.wSecond;
433             d->fraction = st.wMilliseconds * 1000000;
434             break;
435         }
436         default: FIXME("Unimplemented conversion %04x -> DBTIMESTAMP\n", src_type); return E_NOTIMPL;
437         }
438         break;
439     }
440
441     case DBTYPE_CY:
442     {
443         CY *d = dst;
444         switch(src_type)
445         {
446         case DBTYPE_EMPTY:       d->int64 = 0; hr = S_OK;                              break;
447         case DBTYPE_I2:          hr = VarCyFromI2(*(signed short*)src, d);       break;
448         case DBTYPE_I4:          hr = VarCyFromI4(*(signed int*)src, d);         break;
449         case DBTYPE_R4:          hr = VarCyFromR4(*(FLOAT*)src, d);              break;
450         case DBTYPE_R8:          hr = VarCyFromR8(*(double*)src, d);             break;
451         case DBTYPE_CY:          *d = *(CY*)src; hr = S_OK;                      break;
452         case DBTYPE_DATE:        hr = VarCyFromDate(*(DATE*)src, d);             break;
453         case DBTYPE_BSTR:        hr = VarCyFromStr(*(WCHAR**)src, LOCALE_USER_DEFAULT, 0, d); break;
454         case DBTYPE_BOOL:        hr = VarCyFromBool(*(VARIANT_BOOL*)src, d);     break;
455         case DBTYPE_DECIMAL:     hr = VarCyFromDec((DECIMAL*)src, d);            break;
456         case DBTYPE_I1:          hr = VarCyFromI1(*(signed char*)src, d);        break;
457         case DBTYPE_UI1:         hr = VarCyFromUI1(*(BYTE*)src, d);              break;
458         case DBTYPE_UI2:         hr = VarCyFromUI2(*(WORD*)src, d);              break;
459         case DBTYPE_UI4:         hr = VarCyFromUI4(*(DWORD*)src, d);             break;
460         case DBTYPE_I8:          hr = VarCyFromI8(*(LONGLONG*)src, d);           break;
461         case DBTYPE_UI8:         hr = VarCyFromUI8(*(ULONGLONG*)src, d);         break;
462         default: FIXME("Unimplemented conversion %04x -> CY\n", src_type); return E_NOTIMPL;
463         }
464         break;
465     }
466
467     case DBTYPE_BSTR:
468     {
469         BSTR *d = dst;
470         switch(src_type)
471         {
472         case DBTYPE_EMPTY:       *d = SysAllocStringLen(NULL, 0); hr = *d ? S_OK : E_OUTOFMEMORY;      break;
473         case DBTYPE_I2:          hr = VarBstrFromI2(*(signed short*)src, LOCALE_USER_DEFAULT, 0, d);   break;
474         case DBTYPE_I4:          hr = VarBstrFromI4(*(signed int*)src, LOCALE_USER_DEFAULT, 0, d);     break;
475         case DBTYPE_R4:          hr = VarBstrFromR4(*(FLOAT*)src, LOCALE_USER_DEFAULT, 0, d);          break;
476         case DBTYPE_R8:          hr = VarBstrFromR8(*(double*)src, LOCALE_USER_DEFAULT, 0, d);         break;
477         case DBTYPE_CY:          hr = VarBstrFromCy(*(CY*)src, LOCALE_USER_DEFAULT, 0, d);             break;
478         case DBTYPE_DATE:        hr = VarBstrFromDate(*(DATE*)src, LOCALE_USER_DEFAULT, 0, d);         break;
479         case DBTYPE_BSTR:        *d = SysAllocStringLen(*(BSTR*)src, SysStringLen(*(BSTR*)src)); hr = *d ? S_OK : E_OUTOFMEMORY;     break;
480         case DBTYPE_BOOL:        hr = VarBstrFromBool(*(VARIANT_BOOL*)src, LOCALE_USER_DEFAULT, 0, d); break;
481         case DBTYPE_DECIMAL:     hr = VarBstrFromDec((DECIMAL*)src, LOCALE_USER_DEFAULT, 0, d);        break;
482         case DBTYPE_I1:          hr = VarBstrFromI1(*(signed char*)src, LOCALE_USER_DEFAULT, 0, d);    break;
483         case DBTYPE_UI1:         hr = VarBstrFromUI1(*(BYTE*)src, LOCALE_USER_DEFAULT, 0, d);          break;
484         case DBTYPE_UI2:         hr = VarBstrFromUI2(*(WORD*)src, LOCALE_USER_DEFAULT, 0, d);          break;
485         case DBTYPE_UI4:         hr = VarBstrFromUI4(*(DWORD*)src, LOCALE_USER_DEFAULT, 0, d);         break;
486         case DBTYPE_I8:          hr = VarBstrFromI8(*(LONGLONG*)src, LOCALE_USER_DEFAULT, 0, d);       break;
487         case DBTYPE_UI8:         hr = VarBstrFromUI8(*(ULONGLONG*)src, LOCALE_USER_DEFAULT, 0, d);     break;
488         case DBTYPE_GUID:
489         {
490             WCHAR szBuff[39];
491             const GUID *id = (const GUID *)src;
492             WCHAR format[] = {
493                 '{','%','0','8','X','-','%','0','4','X','-','%','0','4','X','-',
494                 '%','0','2','X','%','0','2','X','-',
495                 '%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','}',0};
496             wsprintfW(szBuff, format,
497                 id->Data1, id->Data2, id->Data3,
498                 id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3],
499                 id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7] );
500             *d = SysAllocString(szBuff);
501             hr = *d ? S_OK : E_OUTOFMEMORY;
502         }
503         break;
504         case DBTYPE_BYTES:
505         {
506             *d = SysAllocStringLen(NULL, 2 * src_len);
507             if (*d == NULL)
508                 hr = E_OUTOFMEMORY;
509             else
510             {
511                 const char hexchars[] = "0123456789ABCDEF";
512                 WCHAR *s = *d;
513                 unsigned char *p = src;
514                 while (src_len > 0)
515                 {
516                     *s++ = hexchars[(*p >> 4) & 0x0F];
517                     *s++ = hexchars[(*p)      & 0x0F];
518                     src_len--; p++;
519                 }
520                 hr = S_OK;
521             }
522         }
523         break;
524         case DBTYPE_VARIANT:
525             VariantInit(&tmp);
526             if ((hr = VariantChangeType(&tmp, (VARIANT*)src, 0, VT_BSTR)) == S_OK)
527                 *d = V_BSTR(&tmp);
528             break;
529         default: FIXME("Unimplemented conversion %04x -> BSTR\n", src_type); return E_NOTIMPL;
530         }
531         break;
532     }
533
534     case DBTYPE_UI1:
535     {
536         BYTE *d = dst;
537         switch(src_type)
538         {
539         case DBTYPE_EMPTY:       *d = 0; hr = S_OK;                              break;
540         case DBTYPE_I2:          hr = VarUI1FromI2(*(signed short*)src, d);      break;
541         case DBTYPE_I4:          hr = VarUI1FromI4(*(signed int*)src, d);        break;
542         case DBTYPE_R4:          hr = VarUI1FromR4(*(FLOAT*)src, d);             break;
543         case DBTYPE_R8:          hr = VarUI1FromR8(*(double*)src, d);            break;
544         case DBTYPE_CY:          hr = VarUI1FromCy(*(CY*)src, d);                break;
545         case DBTYPE_DATE:        hr = VarUI1FromDate(*(DATE*)src, d);            break;
546         case DBTYPE_BSTR:        hr = VarUI1FromStr(*(WCHAR**)src, LOCALE_USER_DEFAULT, 0, d); break;
547         case DBTYPE_BOOL:        hr = VarUI1FromBool(*(VARIANT_BOOL*)src, d);    break;
548         case DBTYPE_DECIMAL:     hr = VarUI1FromDec((DECIMAL*)src, d);           break;
549         case DBTYPE_I1:          hr = VarUI1FromI1(*(signed char*)src, d);       break;
550         case DBTYPE_UI1:         *d = *(BYTE*)src; hr = S_OK;                    break;
551         case DBTYPE_UI2:         hr = VarUI1FromUI2(*(WORD*)src, d);             break;
552         case DBTYPE_UI4:         hr = VarUI1FromUI4(*(DWORD*)src, d);            break;
553         case DBTYPE_I8:          hr = VarUI1FromI8(*(LONGLONG*)src, d);          break;
554         case DBTYPE_UI8:         hr = VarUI1FromUI8(*(ULONGLONG*)src, d);        break;
555         default: FIXME("Unimplemented conversion %04x -> UI1\n", src_type); return E_NOTIMPL;
556         }
557         break;
558     }
559     case DBTYPE_UI2:
560     {
561         WORD *d = dst;
562         switch(src_type)
563         {
564         case DBTYPE_EMPTY:       *d = 0; hr = S_OK;                              break;
565         case DBTYPE_I2:          hr = VarUI2FromI2(*(signed short*)src, d);      break;
566         case DBTYPE_I4:          hr = VarUI2FromI4(*(signed int*)src, d);        break;
567         case DBTYPE_R4:          hr = VarUI2FromR4(*(FLOAT*)src, d);             break;
568         case DBTYPE_R8:          hr = VarUI2FromR8(*(double*)src, d);            break;
569         case DBTYPE_CY:          hr = VarUI2FromCy(*(CY*)src, d);                break;
570         case DBTYPE_DATE:        hr = VarUI2FromDate(*(DATE*)src, d);            break;
571         case DBTYPE_BSTR:        hr = VarUI2FromStr(*(WCHAR**)src, LOCALE_USER_DEFAULT, 0, d); break;
572         case DBTYPE_BOOL:        hr = VarUI2FromBool(*(VARIANT_BOOL*)src, d);    break;
573         case DBTYPE_DECIMAL:     hr = VarUI2FromDec((DECIMAL*)src, d);           break;
574         case DBTYPE_I1:          hr = VarUI2FromI1(*(signed char*)src, d);       break;
575         case DBTYPE_UI1:         hr = VarUI2FromUI1(*(BYTE*)src, d);             break;
576         case DBTYPE_UI2:         *d = *(WORD*)src; hr = S_OK;                     break;
577         case DBTYPE_UI4:         hr = VarUI2FromUI4(*(DWORD*)src, d);            break;
578         case DBTYPE_I8:          hr = VarUI2FromI8(*(LONGLONG*)src, d);          break;
579         case DBTYPE_UI8:         hr = VarUI2FromUI8(*(ULONGLONG*)src, d);        break;
580         default: FIXME("Unimplemented conversion %04x -> UI2\n", src_type); return E_NOTIMPL;
581         }
582         break;
583     }
584
585     case DBTYPE_UI4:
586     {
587         DWORD *d = dst;
588         switch(src_type)
589         {
590         case DBTYPE_EMPTY:       *d = 0; hr = S_OK;                              break;
591         case DBTYPE_I2:          hr = VarUI4FromI2(*(signed short*)src, d);      break;
592         case DBTYPE_I4:          hr = VarUI4FromI4(*(signed int*)src, d);        break;
593         case DBTYPE_R4:          hr = VarUI4FromR4(*(FLOAT*)src, d);             break;
594         case DBTYPE_R8:          hr = VarUI4FromR8(*(double*)src, d);            break;
595         case DBTYPE_CY:          hr = VarUI4FromCy(*(CY*)src, d);                break;
596         case DBTYPE_DATE:        hr = VarUI4FromDate(*(DATE*)src, d);            break;
597         case DBTYPE_BSTR:        hr = VarUI4FromStr(*(WCHAR**)src, LOCALE_USER_DEFAULT, 0, d); break;
598         case DBTYPE_BOOL:        hr = VarUI4FromBool(*(VARIANT_BOOL*)src, d);    break;
599         case DBTYPE_DECIMAL:     hr = VarUI4FromDec((DECIMAL*)src, d);           break;
600         case DBTYPE_I1:          hr = VarUI4FromI1(*(signed char*)src, d);       break;
601         case DBTYPE_UI1:         hr = VarUI4FromUI1(*(BYTE*)src, d);             break;
602         case DBTYPE_UI2:         hr = VarUI4FromUI2(*(WORD*)src, d);             break;
603         case DBTYPE_UI4:         *d = *(DWORD*)src; hr = S_OK;                   break;
604         case DBTYPE_I8:          hr = VarUI4FromI8(*(LONGLONG*)src, d);          break;
605         case DBTYPE_UI8:         hr = VarUI4FromUI8(*(ULONGLONG*)src, d);        break;
606         case DBTYPE_VARIANT:
607             VariantInit(&tmp);
608             if ((hr = VariantChangeType(&tmp, (VARIANT*)src, 0, VT_UI4)) == S_OK)
609                 *d = V_UI4(&tmp);
610             break;
611         default: FIXME("Unimplemented conversion %04x -> UI4\n", src_type); return E_NOTIMPL;
612         }
613         break;
614     }
615
616     case DBTYPE_UI8:
617     {
618         ULONGLONG *d = dst;
619         switch(src_type)
620         {
621         case DBTYPE_EMPTY:       *d = 0; hr = S_OK;                              break;
622         case DBTYPE_I2:          hr = VarUI8FromI2(*(signed short*)src, d);      break;
623         case DBTYPE_I4:          {LONGLONG s = *(signed int*)src; hr = VarUI8FromI8(s, d);        break;}
624         case DBTYPE_R4:          hr = VarUI8FromR4(*(FLOAT*)src, d);             break;
625         case DBTYPE_R8:          hr = VarUI8FromR8(*(double*)src, d);            break;
626         case DBTYPE_CY:          hr = VarUI8FromCy(*(CY*)src, d);                break;
627         case DBTYPE_DATE:        hr = VarUI8FromDate(*(DATE*)src, d);            break;
628         case DBTYPE_BSTR:        hr = VarUI8FromStr(*(WCHAR**)src, LOCALE_USER_DEFAULT, 0, d); break;
629         case DBTYPE_BOOL:        hr = VarUI8FromBool(*(VARIANT_BOOL*)src, d);    break;
630         case DBTYPE_DECIMAL:     hr = VarUI8FromDec((DECIMAL*)src, d);           break;
631         case DBTYPE_I1:          hr = VarUI8FromI1(*(signed char*)src, d);       break;
632         case DBTYPE_UI1:         hr = VarUI8FromUI1(*(BYTE*)src, d);             break;
633         case DBTYPE_UI2:         hr = VarUI8FromUI2(*(WORD*)src, d);             break;
634         case DBTYPE_UI4:         hr = VarUI8FromUI4(*(DWORD*)src, d);            break;
635         case DBTYPE_I8:          hr = VarUI8FromI8(*(LONGLONG*)src, d);          break;
636         case DBTYPE_UI8:         *d = *(ULONGLONG*)src; hr = S_OK;               break;
637         default: FIXME("Unimplemented conversion %04x -> UI8\n", src_type); return E_NOTIMPL;
638         }
639         break;
640     }
641
642     case DBTYPE_FILETIME:
643     {
644         FILETIME *d = dst;
645         switch(src_type)
646         {
647         case DBTYPE_EMPTY:       d->dwLowDateTime = d->dwHighDateTime = 0; hr = S_OK;    break;
648         case DBTYPE_FILETIME:    *d = *(FILETIME*)src; hr = S_OK;                        break;
649         default: FIXME("Unimplemented conversion %04x -> FILETIME\n", src_type); return E_NOTIMPL;
650         }
651         break;
652     }
653
654     case DBTYPE_GUID:
655     {
656         GUID *d = dst;
657         switch(src_type)
658         {
659         case DBTYPE_EMPTY:       *d = GUID_NULL; hr = S_OK; break;
660         case DBTYPE_GUID:        *d = *(GUID*)src; hr = S_OK; break;
661         default: FIXME("Unimplemented conversion %04x -> GUID\n", src_type); return E_NOTIMPL;
662         }
663         break;
664     }
665
666     case DBTYPE_WSTR:
667     {
668         BSTR b;
669         DBLENGTH bstr_len;
670         INT bytes_to_copy;
671         hr = IDataConvert_DataConvert(iface, src_type, DBTYPE_BSTR, src_len, &bstr_len,
672                                       src, &b, sizeof(BSTR), src_status, dst_status,
673                                       precision, scale, flags);
674         if(hr != S_OK) return hr;
675         bstr_len = SysStringLen(b);
676         *dst_len = bstr_len * sizeof(WCHAR); /* Doesn't include size for '\0' */
677         *dst_status = DBSTATUS_S_OK;
678         bytes_to_copy = min(*dst_len + sizeof(WCHAR), dst_max_len);
679         if(dst)
680         {
681             if(bytes_to_copy >= sizeof(WCHAR))
682             {
683                 memcpy(dst, b, bytes_to_copy - sizeof(WCHAR));
684                 *((WCHAR*)dst + bytes_to_copy / sizeof(WCHAR) - 1) = 0;
685                 if(bytes_to_copy < *dst_len + sizeof(WCHAR))
686                     *dst_status = DBSTATUS_S_TRUNCATED;
687             }
688             else
689             {
690                 *dst_status = DBSTATUS_E_DATAOVERFLOW;
691                 hr = DB_E_ERRORSOCCURRED;
692             }
693         }
694         SysFreeString(b);
695         return hr;
696     }
697     case DBTYPE_STR:
698     {
699         BSTR b;
700         DBLENGTH bstr_len;
701         INT bytes_to_copy;
702         hr = IDataConvert_DataConvert(iface, src_type, DBTYPE_BSTR, src_len, &bstr_len,
703                                       src, &b, sizeof(BSTR), src_status, dst_status,
704                                       precision, scale, flags);
705         if(hr != S_OK) return hr;
706         bstr_len = SysStringLen(b);
707         *dst_len = bstr_len * sizeof(char); /* Doesn't include size for '\0' */
708         *dst_status = DBSTATUS_S_OK;
709         bytes_to_copy = min(*dst_len + sizeof(char), dst_max_len);
710         if(dst)
711         {
712             if(bytes_to_copy >= sizeof(char))
713             {
714                 WideCharToMultiByte(CP_ACP, 0, b, bytes_to_copy - sizeof(char), dst, dst_max_len, NULL, NULL);
715                 *((char *)dst + bytes_to_copy / sizeof(char) - 1) = 0;
716                 if(bytes_to_copy < *dst_len + sizeof(char))
717                     *dst_status = DBSTATUS_S_TRUNCATED;
718             }
719             else
720             {
721                 *dst_status = DBSTATUS_E_DATAOVERFLOW;
722                 hr = DB_E_ERRORSOCCURRED;
723             }
724         }
725         SysFreeString(b);
726         return hr;
727     }
728
729     case DBTYPE_BYREF | DBTYPE_WSTR:
730     {
731         BSTR b;
732         WCHAR **d = dst;
733         DBLENGTH bstr_len;
734         hr = IDataConvert_DataConvert(iface, src_type, DBTYPE_BSTR, src_len, &bstr_len,
735                                       src, &b, sizeof(BSTR), src_status, dst_status,
736                                       precision, scale, flags);
737         if(hr != S_OK) return hr;
738
739         bstr_len = SysStringLen(b) * sizeof(WCHAR);
740         *dst_len = bstr_len; /* Doesn't include size for '\0' */
741
742         *d = CoTaskMemAlloc(bstr_len + sizeof(WCHAR));
743         if(*d) memcpy(*d, b, bstr_len + sizeof(WCHAR));
744         else hr = E_OUTOFMEMORY;
745         SysFreeString(b);
746         return hr;
747     }
748
749     case DBTYPE_VARIANT:
750     {
751         VARIANT *v = dst;
752
753         switch(src_type)
754         {
755         case DBTYPE_BOOL:
756             V_VT(v) = VT_BOOL;
757             V_BOOL(v) = *(VARIANT_BOOL*)src;
758             hr = S_OK;
759             break;
760         case DBTYPE_I4:
761             V_VT(v) = VT_I4;
762             V_I4(v) = *(signed int*)src;
763             hr = S_OK;
764             break;
765         case DBTYPE_I8:
766             V_VT(v) = VT_DECIMAL;
767             hr = VarDecFromI8( *(LONGLONG*)src,  &V_DECIMAL(v));
768             break;
769         case DBTYPE_R8:
770             V_VT(v) = VT_R8;
771             V_R8(v) = *(double*)src;
772             hr = S_OK;
773             break;
774         case DBTYPE_BSTR:
775         {
776             BSTR s = *(WCHAR**)src;
777             TRACE("%s\n", debugstr_w(s));
778             V_VT(v) = VT_BSTR;
779             V_BSTR(v) = SysAllocString(s);
780             hr = V_BSTR(v) ? S_OK : E_OUTOFMEMORY;
781             break;
782         }
783         case DBTYPE_DATE:
784             V_VT(v) = VT_DATE;
785             V_DATE(v) = *(DATE*)src;
786             hr = S_OK;
787             break;
788         case DBTYPE_CY:
789             V_VT(v) = VT_CY;
790             V_CY(v) = *(CY*)src;
791             hr = S_OK;
792             break;
793         default: FIXME("Unimplemented conversion %04x -> VARIANT\n", src_type); return E_NOTIMPL;
794         }
795         break;
796     }
797
798     default:
799         FIXME("Unimplemented conversion %04x -> %04x\n", src_type, dst_type);
800         return E_NOTIMPL;
801     }
802
803     if(hr == DISP_E_OVERFLOW)
804     {
805         *dst_status = DBSTATUS_E_DATAOVERFLOW;
806         *dst_len = get_length(dst_type);
807         hr = DB_E_ERRORSOCCURRED;
808     }
809     else if(hr == S_OK)
810     {
811         *dst_status = DBSTATUS_S_OK;
812         *dst_len = get_length(dst_type);
813     }
814
815     return hr;
816 }
817
818 static inline WORD get_dbtype_class(DBTYPE type)
819 {
820     switch(type)
821     {
822     case DBTYPE_I2:
823     case DBTYPE_R4:
824     case DBTYPE_R8:
825     case DBTYPE_I1:
826     case DBTYPE_UI1:
827     case DBTYPE_UI2:
828         return DBTYPE_I2;
829
830     case DBTYPE_I4:
831     case DBTYPE_UI4:
832         return DBTYPE_I4;
833
834     case DBTYPE_I8:
835     case DBTYPE_UI8:
836         return DBTYPE_I8;
837
838     case DBTYPE_BSTR:
839     case DBTYPE_STR:
840     case DBTYPE_WSTR:
841         return DBTYPE_BSTR;
842
843     case DBTYPE_DBDATE:
844     case DBTYPE_DBTIME:
845     case DBTYPE_DBTIMESTAMP:
846         return DBTYPE_DBDATE;
847     }
848     return type;
849 }
850
851 /* Many src types will convert to this group of dst types */
852 static inline BOOL common_class(WORD dst_class)
853 {
854     switch(dst_class)
855     {
856     case DBTYPE_EMPTY:
857     case DBTYPE_NULL:
858     case DBTYPE_I2:
859     case DBTYPE_I4:
860     case DBTYPE_BSTR:
861     case DBTYPE_BOOL:
862     case DBTYPE_VARIANT:
863     case DBTYPE_I8:
864     case DBTYPE_CY:
865     case DBTYPE_DECIMAL:
866     case DBTYPE_NUMERIC:
867         return TRUE;
868     }
869     return FALSE;
870 }
871
872 static inline BOOL array_type(DBTYPE type)
873 {
874     return (type >= DBTYPE_I2 && type <= DBTYPE_UI4);
875 }
876
877 static HRESULT WINAPI convert_CanConvert(IDataConvert* iface,
878                                          DBTYPE src_type, DBTYPE dst_type)
879 {
880     convert *This = impl_from_IDataConvert(iface);
881     DBTYPE src_base_type = src_type & 0x1ff;
882     DBTYPE dst_base_type = dst_type & 0x1ff;
883     WORD dst_class = get_dbtype_class(dst_base_type);
884
885     TRACE("(%p)->(%d, %d)\n", This, src_type, dst_type);
886
887     if(src_type & DBTYPE_VECTOR || dst_type & DBTYPE_VECTOR) return S_FALSE;
888
889     if(src_type & DBTYPE_ARRAY)
890     {
891         if(!array_type(src_base_type)) return S_FALSE;
892         if(dst_type & DBTYPE_ARRAY)
893         {
894             if(src_type == dst_type) return S_OK;
895             return S_FALSE;
896         }
897         if(dst_type == DBTYPE_VARIANT) return S_OK;
898         return S_FALSE;
899     }
900
901     if(dst_type & DBTYPE_ARRAY)
902     {
903         if(!array_type(dst_base_type)) return S_FALSE;
904         if(src_type == DBTYPE_IDISPATCH || src_type == DBTYPE_VARIANT) return S_OK;
905         return S_FALSE;
906     }
907
908     if(dst_type & DBTYPE_BYREF)
909         if(dst_base_type != DBTYPE_BYTES && dst_base_type != DBTYPE_STR && dst_base_type != DBTYPE_WSTR)
910             return S_FALSE;
911
912     switch(get_dbtype_class(src_base_type))
913     {
914     case DBTYPE_EMPTY:
915         if(common_class(dst_class)) return S_OK;
916         switch(dst_class)
917         {
918         case DBTYPE_DATE:
919         case DBTYPE_GUID:
920         case DBTYPE_FILETIME:
921             return S_OK;
922         default:
923             if(dst_base_type == DBTYPE_DBTIMESTAMP) return S_OK;
924             return S_FALSE;
925         }
926
927     case DBTYPE_NULL:
928         switch(dst_base_type)
929         {
930         case DBTYPE_NULL:
931         case DBTYPE_VARIANT:
932         case DBTYPE_FILETIME: return S_OK;
933         default: return S_FALSE;
934         }
935
936     case DBTYPE_I4:
937         if(dst_base_type == DBTYPE_BYTES) return S_OK;
938         /* fall through */
939     case DBTYPE_I2:
940         if(dst_base_type == DBTYPE_DATE) return S_OK;
941         /* fall through */
942     case DBTYPE_DECIMAL:
943         if(common_class(dst_class)) return S_OK;
944         if(dst_class == DBTYPE_DBDATE) return S_OK;
945         return S_FALSE;
946
947     case DBTYPE_BOOL:
948         if(dst_base_type == DBTYPE_DATE) return S_OK;
949         /* fall through */
950     case DBTYPE_NUMERIC:
951     case DBTYPE_CY:
952         if(common_class(dst_class)) return S_OK;
953         return S_FALSE;
954
955     case DBTYPE_I8:
956         if(common_class(dst_class)) return S_OK;
957         switch(dst_base_type)
958         {
959         case DBTYPE_BYTES:
960         case DBTYPE_FILETIME: return S_OK;
961         default: return S_FALSE;
962         }
963
964     case DBTYPE_DATE:
965         switch(dst_class)
966         {
967         case DBTYPE_EMPTY:
968         case DBTYPE_NULL:
969         case DBTYPE_I2:
970         case DBTYPE_I4:
971         case DBTYPE_BSTR:
972         case DBTYPE_BOOL:
973         case DBTYPE_VARIANT:
974         case DBTYPE_I8:
975         case DBTYPE_DATE:
976         case DBTYPE_DBDATE:
977         case DBTYPE_FILETIME:
978             return S_OK;
979         default: return S_FALSE;
980         }
981
982     case DBTYPE_IDISPATCH:
983     case DBTYPE_VARIANT:
984         switch(dst_base_type)
985         {
986         case DBTYPE_IDISPATCH:
987         case DBTYPE_ERROR:
988         case DBTYPE_IUNKNOWN:
989             return S_OK;
990         }
991         /* fall through */
992     case DBTYPE_BSTR:
993         if(common_class(dst_class)) return S_OK;
994         switch(dst_class)
995         {
996         case DBTYPE_DATE:
997         case DBTYPE_GUID:
998         case DBTYPE_BYTES:
999         case DBTYPE_DBDATE:
1000         case DBTYPE_FILETIME:
1001             return S_OK;
1002         default: return S_FALSE;
1003         }
1004
1005     case DBTYPE_ERROR:
1006         switch(dst_base_type)
1007         {
1008         case DBTYPE_BSTR:
1009         case DBTYPE_ERROR:
1010         case DBTYPE_VARIANT:
1011         case DBTYPE_WSTR:
1012             return S_OK;
1013         default: return S_FALSE;
1014         }
1015
1016     case DBTYPE_IUNKNOWN:
1017         switch(dst_base_type)
1018         {
1019         case DBTYPE_EMPTY:
1020         case DBTYPE_NULL:
1021         case DBTYPE_IDISPATCH:
1022         case DBTYPE_VARIANT:
1023         case DBTYPE_IUNKNOWN:
1024             return S_OK;
1025         default: return S_FALSE;
1026         }
1027
1028     case DBTYPE_BYTES:
1029         if(dst_class == DBTYPE_I4 || dst_class == DBTYPE_I8) return S_OK;
1030         /* fall through */
1031     case DBTYPE_GUID:
1032         switch(dst_class)
1033         {
1034         case DBTYPE_EMPTY:
1035         case DBTYPE_NULL:
1036         case DBTYPE_BSTR:
1037         case DBTYPE_VARIANT:
1038         case DBTYPE_GUID:
1039         case DBTYPE_BYTES:
1040             return S_OK;
1041         default: return S_FALSE;
1042         }
1043
1044     case DBTYPE_FILETIME:
1045         if(dst_class == DBTYPE_I8) return S_OK;
1046         /* fall through */
1047     case DBTYPE_DBDATE:
1048         switch(dst_class)
1049         {
1050         case DBTYPE_EMPTY:
1051         case DBTYPE_NULL:
1052         case DBTYPE_DATE:
1053         case DBTYPE_BSTR:
1054         case DBTYPE_VARIANT:
1055         case DBTYPE_DBDATE:
1056         case DBTYPE_FILETIME:
1057             return S_OK;
1058         default: return S_FALSE;
1059         }
1060
1061     }
1062     return S_FALSE;
1063 }
1064
1065 static HRESULT WINAPI convert_GetConversionSize(IDataConvert* iface,
1066                                                 DBTYPE src_type, DBTYPE dst_type,
1067                                                 DBLENGTH *src_len, DBLENGTH *dst_len,
1068                                                 void *src)
1069 {
1070     convert *This = impl_from_IDataConvert(iface);
1071     HRESULT hr;
1072
1073     TRACE("(%p)->(%d, %d, %p, %p, %p)\n", This, src_type, dst_type, src_len, dst_len, src);
1074
1075     hr = IDataConvert_CanConvert(iface, src_type, dst_type);
1076     if (hr != S_OK)
1077         return DB_E_UNSUPPORTEDCONVERSION;
1078
1079     if (!dst_len)
1080         return E_INVALIDARG;
1081
1082     /* for some types we don't need to look into source data */
1083     if ((*dst_len = get_length(dst_type)))
1084         return S_OK;
1085
1086     switch (dst_type)
1087     {
1088     case DBTYPE_STR:
1089     {
1090         switch (src_type)
1091         {
1092         case DBTYPE_VARIANT:
1093         {
1094             VARIANT v;
1095
1096             VariantInit(&v);
1097             if ((hr = VariantChangeType(&v, (VARIANT*)src, 0, VT_BSTR)) == S_OK)
1098             {
1099                 *dst_len = WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), -1, NULL, 0, NULL, NULL);
1100                 VariantClear(&v);
1101             }
1102             else
1103                 return hr;
1104         }
1105         break;
1106         default:
1107             FIXME("unimplemented for %04x -> DBTYPE_STR\n", src_type);
1108             return E_NOTIMPL;
1109         }
1110     }
1111     break;
1112     case DBTYPE_WSTR:
1113     {
1114         switch (src_type)
1115         {
1116         case DBTYPE_STR:
1117             if(src_len)
1118                 *dst_len = (*src_len + 1) * sizeof(WCHAR);
1119             else
1120                 *dst_len = (strlen(src) + 1) * sizeof(WCHAR);
1121             break;
1122         case DBTYPE_WSTR:
1123             if(src_len)
1124                 *dst_len = (*src_len) + sizeof(WCHAR);
1125             else
1126                 *dst_len = (lstrlenW(src) + 1) * sizeof(WCHAR);
1127             break;
1128         default:
1129             FIXME("unimplemented for %04x -> DBTYPE_WSTR\n", src_type);
1130             return E_NOTIMPL;
1131         }
1132     }
1133     break;
1134     default:
1135         FIXME("unimplemented for conversion %d->%d\n", src_type, dst_type);
1136         return E_NOTIMPL;
1137     }
1138
1139     return S_OK;
1140 }
1141
1142 static const struct IDataConvertVtbl convert_vtbl =
1143 {
1144     convert_QueryInterface,
1145     convert_AddRef,
1146     convert_Release,
1147     convert_DataConvert,
1148     convert_CanConvert,
1149     convert_GetConversionSize
1150 };
1151
1152 static HRESULT WINAPI dcinfo_QueryInterface(IDCInfo* iface, REFIID riid, void **obj)
1153 {
1154     convert *This = impl_from_IDCInfo(iface);
1155
1156     return IDataConvert_QueryInterface(&This->IDataConvert_iface, riid, obj);
1157 }
1158
1159 static ULONG WINAPI dcinfo_AddRef(IDCInfo* iface)
1160 {
1161     convert *This = impl_from_IDCInfo(iface);
1162
1163     return IDataConvert_AddRef(&This->IDataConvert_iface);
1164 }
1165
1166 static ULONG WINAPI dcinfo_Release(IDCInfo* iface)
1167 {
1168     convert *This = impl_from_IDCInfo(iface);
1169
1170     return IDataConvert_Release(&This->IDataConvert_iface);
1171 }
1172
1173 static HRESULT WINAPI dcinfo_GetInfo(IDCInfo *iface, ULONG num, DCINFOTYPE types[], DCINFO **info_ptr)
1174 {
1175     convert *This = impl_from_IDCInfo(iface);
1176     ULONG i;
1177     DCINFO *infos;
1178
1179     TRACE("(%p)->(%d, %p, %p)\n", This, num, types, info_ptr);
1180
1181     *info_ptr = infos = CoTaskMemAlloc(num * sizeof(*infos));
1182     if(!infos) return E_OUTOFMEMORY;
1183
1184     for(i = 0; i < num; i++)
1185     {
1186         infos[i].eInfoType = types[i];
1187         VariantInit(&infos[i].vData);
1188
1189         switch(types[i])
1190         {
1191         case DCINFOTYPE_VERSION:
1192             V_VT(&infos[i].vData) = VT_UI4;
1193             V_UI4(&infos[i].vData) = This->version;
1194             break;
1195         }
1196     }
1197
1198     return S_OK;
1199 }
1200
1201 static HRESULT WINAPI dcinfo_SetInfo(IDCInfo* iface, ULONG num, DCINFO info[])
1202 {
1203     convert *This = impl_from_IDCInfo(iface);
1204     ULONG i;
1205     HRESULT hr = S_OK;
1206
1207     TRACE("(%p)->(%d, %p)\n", This, num, info);
1208
1209     for(i = 0; i < num; i++)
1210     {
1211         switch(info[i].eInfoType)
1212         {
1213         case DCINFOTYPE_VERSION:
1214             if(V_VT(&info[i].vData) != VT_UI4)
1215             {
1216                 FIXME("VERSION with vt %x\n", V_VT(&info[i].vData));
1217                 hr = DB_S_ERRORSOCCURRED;
1218                 break;
1219             }
1220             This->version = V_UI4(&info[i].vData);
1221             break;
1222
1223         default:
1224             FIXME("Unhandled info type %d (vt %x)\n", info[i].eInfoType, V_VT(&info[i].vData));
1225         }
1226     }
1227     return hr;
1228 }
1229
1230 static const struct IDCInfoVtbl dcinfo_vtbl =
1231 {
1232     dcinfo_QueryInterface,
1233     dcinfo_AddRef,
1234     dcinfo_Release,
1235     dcinfo_GetInfo,
1236     dcinfo_SetInfo
1237 };
1238
1239 HRESULT create_oledb_convert(IUnknown *outer, void **obj)
1240 {
1241     convert *This;
1242
1243     TRACE("(%p, %p)\n", outer, obj);
1244
1245     *obj = NULL;
1246
1247     if(outer) return CLASS_E_NOAGGREGATION;
1248
1249     This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1250     if(!This) return E_OUTOFMEMORY;
1251
1252     This->IDataConvert_iface.lpVtbl = &convert_vtbl;
1253     This->IDCInfo_iface.lpVtbl = &dcinfo_vtbl;
1254     This->ref = 1;
1255     This->version = 0x110;
1256
1257     *obj = &This->IDataConvert_iface;
1258
1259     return S_OK;
1260 }