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