oledb32: Implement GetConversionSize DBTYPE_STR->DBTYPE_WSTR.
[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_I8:
291     {
292         LONGLONG *d = dst;
293         switch(src_type)
294         {
295         case DBTYPE_BSTR:        hr = VarI8FromStr(*(WCHAR**)src, LOCALE_USER_DEFAULT, 0, d); break;
296         case DBTYPE_I8:          *d = *(LONGLONG*)src; hr = S_OK;              break;
297         default: FIXME("Unimplemented conversion %04x -> I8\n", src_type); return E_NOTIMPL;
298         }
299         break;
300     }
301
302     case DBTYPE_R4:
303     {
304         FLOAT *d = dst;
305         switch(src_type)
306         {
307         case DBTYPE_EMPTY:       *d = 0; hr = S_OK;                              break;
308         case DBTYPE_I2:          hr = VarR4FromI2(*(signed short*)src, d);       break;
309         case DBTYPE_I4:          hr = VarR4FromI4(*(signed int*)src, d);         break;
310         case DBTYPE_R4:          *d = *(FLOAT*)src; hr = S_OK;                   break;
311         case DBTYPE_R8:          hr = VarR4FromR8(*(double*)src, d);             break;
312         case DBTYPE_CY:          hr = VarR4FromCy(*(CY*)src, d);                 break;
313         case DBTYPE_DATE:        hr = VarR4FromDate(*(DATE*)src, d);             break;
314         case DBTYPE_BSTR:        hr = VarR4FromStr(*(WCHAR**)src, LOCALE_USER_DEFAULT, 0, d); break;
315         case DBTYPE_BOOL:        hr = VarR4FromBool(*(VARIANT_BOOL*)src, d);     break;
316         case DBTYPE_DECIMAL:     hr = VarR4FromDec((DECIMAL*)src, d);            break;
317         case DBTYPE_I1:          hr = VarR4FromI1(*(signed char*)src, d);        break;
318         case DBTYPE_UI1:         hr = VarR4FromUI1(*(BYTE*)src, d);              break;
319         case DBTYPE_UI2:         hr = VarR4FromUI2(*(WORD*)src, d);              break;
320         case DBTYPE_UI4:         hr = VarR4FromUI4(*(DWORD*)src, d);             break;
321         case DBTYPE_I8:          hr = VarR4FromI8(*(LONGLONG*)src, d);           break;
322         case DBTYPE_UI8:         hr = VarR4FromUI8(*(ULONGLONG*)src, d);         break;
323         default: FIXME("Unimplemented conversion %04x -> R4\n", src_type); return E_NOTIMPL;
324         }
325         break;
326     }
327     case DBTYPE_R8:
328     {
329         DOUBLE *d=dst;
330         switch (src_type)
331         {
332         case DBTYPE_EMPTY:      *d = 0; hr = S_OK;                               break;
333         case DBTYPE_I1:          hr = VarR8FromI1(*(signed char*)src, d);        break;
334         case DBTYPE_I2:          hr = VarR8FromI2(*(signed short*)src, d);       break;
335         case DBTYPE_I4:          hr = VarR8FromI4(*(signed int*)src, d);         break;
336         case DBTYPE_I8:          hr = VarR8FromI8(*(LONGLONG*)src, d);           break;
337         case DBTYPE_UI1:         hr = VarR8FromUI1(*(BYTE*)src, d);              break;
338         case DBTYPE_UI2:         hr = VarR8FromUI2(*(WORD*)src, d);              break;
339         case DBTYPE_UI4:         hr = VarR8FromUI4(*(DWORD*)src, d);             break;
340         case DBTYPE_UI8:         hr = VarR8FromUI8(*(ULONGLONG*)src, d);         break;
341         case DBTYPE_R4:          hr = VarR8FromR4(*(FLOAT*)src, d);              break;
342         case DBTYPE_R8:          *d = *(DOUBLE*)src; hr = S_OK;                  break;
343         case DBTYPE_CY:          hr = VarR8FromCy(*(CY*)src, d);                 break;
344         case DBTYPE_DATE:        hr = VarR8FromDate(*(DATE*)src, d);             break;
345         case DBTYPE_BSTR:        hr = VarR8FromStr(*(WCHAR**)src, LOCALE_USER_DEFAULT, 0, d); break;
346         case DBTYPE_BOOL:        hr = VarR8FromBool(*(VARIANT_BOOL*)src, d);     break;
347         case DBTYPE_DECIMAL:     hr = VarR8FromDec((DECIMAL*)src, d);            break;
348         default: FIXME("Unimplemented conversion %04x -> R8\n", src_type); return E_NOTIMPL;
349         }
350         break;
351     }
352     case DBTYPE_BOOL:
353     {
354         VARIANT_BOOL *d=dst;
355         switch (src_type)
356         {
357         case DBTYPE_EMPTY:      *d = 0; hr = S_OK;                               break;
358         case DBTYPE_I1:          hr = VarBoolFromI1(*(signed char*)src, d);      break;
359         case DBTYPE_I2:          hr = VarBoolFromI2(*(signed short*)src, d);     break;
360         case DBTYPE_I4:          hr = VarBoolFromI4(*(signed int*)src, d);       break;
361         case DBTYPE_I8:          hr = VarBoolFromI8(*(LONGLONG*)src, d);         break;
362         case DBTYPE_UI1:         hr = VarBoolFromUI1(*(BYTE*)src, d);            break;
363         case DBTYPE_UI2:         hr = VarBoolFromUI2(*(WORD*)src, d);            break;
364         case DBTYPE_UI4:         hr = VarBoolFromUI4(*(DWORD*)src, d);           break;
365         case DBTYPE_UI8:         hr = VarBoolFromUI8(*(ULONGLONG*)src, d);       break;
366         case DBTYPE_R4:          hr = VarBoolFromR4(*(FLOAT*)src, d);            break;
367         case DBTYPE_R8:          hr = VarBoolFromR8(*(DOUBLE*)src, d);           break;
368         case DBTYPE_CY:          hr = VarBoolFromCy(*(CY*)src, d);               break;
369         case DBTYPE_DATE:        hr = VarBoolFromDate(*(DATE*)src, d);           break;
370         case DBTYPE_BSTR:        hr = VarBoolFromStr(*(WCHAR**)src, LOCALE_USER_DEFAULT, 0, d); break;
371         case DBTYPE_BOOL:        *d = *(VARIANT_BOOL*)src; hr = S_OK;            break;
372         case DBTYPE_DECIMAL:     hr = VarBoolFromDec((DECIMAL*)src, d);          break;
373         default: FIXME("Unimplemented conversion %04x -> BOOL\n", src_type); return E_NOTIMPL;
374         }
375         break;
376     }
377     case DBTYPE_DATE:
378     {
379         DATE *d=dst;
380         switch (src_type)
381         {
382         case DBTYPE_EMPTY:      *d = 0; hr = S_OK;                               break;
383         case DBTYPE_I1:          hr = VarDateFromI1(*(signed char*)src, d);      break;
384         case DBTYPE_I2:          hr = VarDateFromI2(*(signed short*)src, d);     break;
385         case DBTYPE_I4:          hr = VarDateFromI4(*(signed int*)src, d);       break;
386         case DBTYPE_I8:          hr = VarDateFromI8(*(LONGLONG*)src, d);         break;
387         case DBTYPE_UI1:         hr = VarDateFromUI1(*(BYTE*)src, d);            break;
388         case DBTYPE_UI2:         hr = VarDateFromUI2(*(WORD*)src, d);            break;
389         case DBTYPE_UI4:         hr = VarDateFromUI4(*(DWORD*)src, d);           break;
390         case DBTYPE_UI8:         hr = VarDateFromUI8(*(ULONGLONG*)src, d);       break;
391         case DBTYPE_R4:          hr = VarDateFromR4(*(FLOAT*)src, d);            break;
392         case DBTYPE_R8:          hr = VarDateFromR8(*(DOUBLE*)src, d);           break;
393         case DBTYPE_CY:          hr = VarDateFromCy(*(CY*)src, d);               break;
394         case DBTYPE_DATE:       *d = *(DATE*)src;      hr = S_OK;                break;
395         case DBTYPE_BSTR:        hr = VarDateFromStr(*(WCHAR**)src, LOCALE_USER_DEFAULT, 0, d); break;
396         case DBTYPE_BOOL:        hr = VarDateFromBool(*(VARIANT_BOOL*)src, d);   break;
397         case DBTYPE_DECIMAL:     hr = VarDateFromDec((DECIMAL*)src, d);          break;
398         case DBTYPE_DBTIMESTAMP:
399         {
400             SYSTEMTIME st;
401             DBTIMESTAMP *ts=(DBTIMESTAMP*)src;
402
403             st.wYear = ts->year;
404             st.wMonth = ts->month;
405             st.wDay = ts->day;
406             st.wHour = ts->hour;
407             st.wMinute = ts->minute;
408             st.wSecond = ts->second;
409             st.wMilliseconds = ts->fraction/1000000;
410             hr = (SystemTimeToVariantTime(&st, d) ? S_OK : E_FAIL);
411             break;
412         }
413         default: FIXME("Unimplemented conversion %04x -> DATE\n", src_type); return E_NOTIMPL;
414         }
415         break;
416     }
417     case DBTYPE_DBTIMESTAMP:
418     {
419         DBTIMESTAMP *d=dst;
420         switch (src_type)
421         {
422         case DBTYPE_EMPTY:       memset(d, 0, sizeof(DBTIMESTAMP));    hr = S_OK; break;
423         case DBTYPE_DBTIMESTAMP: memcpy(d, src, sizeof(DBTIMESTAMP));  hr = S_OK; break;
424         case DBTYPE_DATE:
425         {
426             SYSTEMTIME st;
427             hr = (VariantTimeToSystemTime(*(double*)src, &st) ? S_OK : E_FAIL);
428             d->year = st.wYear;
429             d->month = st.wMonth;
430             d->day = st.wDay;
431             d->hour = st.wHour;
432             d->minute = st.wMinute;
433             d->second = st.wSecond;
434             d->fraction = st.wMilliseconds * 1000000;
435             break;
436         }
437         default: FIXME("Unimplemented conversion %04x -> DBTIMESTAMP\n", src_type); return E_NOTIMPL;
438         }
439         break;
440     }
441
442     case DBTYPE_CY:
443     {
444         CY *d = dst;
445         switch(src_type)
446         {
447         case DBTYPE_EMPTY:       d->int64 = 0; hr = S_OK;                              break;
448         case DBTYPE_I2:          hr = VarCyFromI2(*(signed short*)src, d);       break;
449         case DBTYPE_I4:          hr = VarCyFromI4(*(signed int*)src, d);         break;
450         case DBTYPE_R4:          hr = VarCyFromR4(*(FLOAT*)src, d);              break;
451         case DBTYPE_R8:          hr = VarCyFromR8(*(double*)src, d);             break;
452         case DBTYPE_CY:          *d = *(CY*)src; hr = S_OK;                      break;
453         case DBTYPE_DATE:        hr = VarCyFromDate(*(DATE*)src, d);             break;
454         case DBTYPE_BSTR:        hr = VarCyFromStr(*(WCHAR**)src, LOCALE_USER_DEFAULT, 0, d); break;
455         case DBTYPE_BOOL:        hr = VarCyFromBool(*(VARIANT_BOOL*)src, d);     break;
456         case DBTYPE_DECIMAL:     hr = VarCyFromDec((DECIMAL*)src, d);            break;
457         case DBTYPE_I1:          hr = VarCyFromI1(*(signed char*)src, d);        break;
458         case DBTYPE_UI1:         hr = VarCyFromUI1(*(BYTE*)src, d);              break;
459         case DBTYPE_UI2:         hr = VarCyFromUI2(*(WORD*)src, d);              break;
460         case DBTYPE_UI4:         hr = VarCyFromUI4(*(DWORD*)src, d);             break;
461         case DBTYPE_I8:          hr = VarCyFromI8(*(LONGLONG*)src, d);           break;
462         case DBTYPE_UI8:         hr = VarCyFromUI8(*(ULONGLONG*)src, d);         break;
463         default: FIXME("Unimplemented conversion %04x -> CY\n", src_type); return E_NOTIMPL;
464         }
465         break;
466     }
467
468     case DBTYPE_BSTR:
469     {
470         BSTR *d = dst;
471         switch(src_type)
472         {
473         case DBTYPE_EMPTY:       *d = SysAllocStringLen(NULL, 0); hr = *d ? S_OK : E_OUTOFMEMORY;      break;
474         case DBTYPE_I2:          hr = VarBstrFromI2(*(signed short*)src, LOCALE_USER_DEFAULT, 0, d);   break;
475         case DBTYPE_I4:          hr = VarBstrFromI4(*(signed int*)src, LOCALE_USER_DEFAULT, 0, d);     break;
476         case DBTYPE_R4:          hr = VarBstrFromR4(*(FLOAT*)src, LOCALE_USER_DEFAULT, 0, d);          break;
477         case DBTYPE_R8:          hr = VarBstrFromR8(*(double*)src, LOCALE_USER_DEFAULT, 0, d);         break;
478         case DBTYPE_CY:          hr = VarBstrFromCy(*(CY*)src, LOCALE_USER_DEFAULT, 0, d);             break;
479         case DBTYPE_DATE:        hr = VarBstrFromDate(*(DATE*)src, LOCALE_USER_DEFAULT, 0, d);         break;
480         case DBTYPE_BSTR:        *d = SysAllocStringLen(*(BSTR*)src, SysStringLen(*(BSTR*)src)); hr = *d ? S_OK : E_OUTOFMEMORY;     break;
481         case DBTYPE_BOOL:        hr = VarBstrFromBool(*(VARIANT_BOOL*)src, LOCALE_USER_DEFAULT, 0, d); break;
482         case DBTYPE_DECIMAL:     hr = VarBstrFromDec((DECIMAL*)src, LOCALE_USER_DEFAULT, 0, d);        break;
483         case DBTYPE_I1:          hr = VarBstrFromI1(*(signed char*)src, LOCALE_USER_DEFAULT, 0, d);    break;
484         case DBTYPE_UI1:         hr = VarBstrFromUI1(*(BYTE*)src, LOCALE_USER_DEFAULT, 0, d);          break;
485         case DBTYPE_UI2:         hr = VarBstrFromUI2(*(WORD*)src, LOCALE_USER_DEFAULT, 0, d);          break;
486         case DBTYPE_UI4:         hr = VarBstrFromUI4(*(DWORD*)src, LOCALE_USER_DEFAULT, 0, d);         break;
487         case DBTYPE_I8:          hr = VarBstrFromI8(*(LONGLONG*)src, LOCALE_USER_DEFAULT, 0, d);       break;
488         case DBTYPE_UI8:         hr = VarBstrFromUI8(*(ULONGLONG*)src, LOCALE_USER_DEFAULT, 0, d);     break;
489         case DBTYPE_GUID:
490         {
491             WCHAR szBuff[39];
492             const GUID *id = (const GUID *)src;
493             WCHAR format[] = {
494                 '{','%','0','8','X','-','%','0','4','X','-','%','0','4','X','-',
495                 '%','0','2','X','%','0','2','X','-',
496                 '%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','}',0};
497             wsprintfW(szBuff, format,
498                 id->Data1, id->Data2, id->Data3,
499                 id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3],
500                 id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7] );
501             *d = SysAllocString(szBuff);
502             hr = *d ? S_OK : E_OUTOFMEMORY;
503         }
504         break;
505         case DBTYPE_BYTES:
506         {
507             *d = SysAllocStringLen(NULL, 2 * src_len);
508             if (*d == NULL)
509                 hr = E_OUTOFMEMORY;
510             else
511             {
512                 const char hexchars[] = "0123456789ABCDEF";
513                 WCHAR *s = *d;
514                 unsigned char *p = src;
515                 while (src_len > 0)
516                 {
517                     *s++ = hexchars[(*p >> 4) & 0x0F];
518                     *s++ = hexchars[(*p)      & 0x0F];
519                     src_len--; p++;
520                 }
521                 hr = S_OK;
522             }
523         }
524         break;
525         case DBTYPE_VARIANT:
526         {
527             VARIANT tmp;
528
529             VariantInit(&tmp);
530             if ((hr = VariantChangeType(&tmp, (VARIANT*)src, 0, VT_BSTR)) == S_OK)
531                 *d = V_BSTR(&tmp);
532         }
533         break;
534         default: FIXME("Unimplemented conversion %04x -> BSTR\n", src_type); return E_NOTIMPL;
535         }
536         break;
537     }
538
539     case DBTYPE_UI1:
540     {
541         BYTE *d = dst;
542         switch(src_type)
543         {
544         case DBTYPE_EMPTY:       *d = 0; hr = S_OK;                              break;
545         case DBTYPE_I2:          hr = VarUI1FromI2(*(signed short*)src, d);      break;
546         case DBTYPE_I4:          hr = VarUI1FromI4(*(signed int*)src, d);        break;
547         case DBTYPE_R4:          hr = VarUI1FromR4(*(FLOAT*)src, d);             break;
548         case DBTYPE_R8:          hr = VarUI1FromR8(*(double*)src, d);            break;
549         case DBTYPE_CY:          hr = VarUI1FromCy(*(CY*)src, d);                break;
550         case DBTYPE_DATE:        hr = VarUI1FromDate(*(DATE*)src, d);            break;
551         case DBTYPE_BSTR:        hr = VarUI1FromStr(*(WCHAR**)src, LOCALE_USER_DEFAULT, 0, d); break;
552         case DBTYPE_BOOL:        hr = VarUI1FromBool(*(VARIANT_BOOL*)src, d);    break;
553         case DBTYPE_DECIMAL:     hr = VarUI1FromDec((DECIMAL*)src, d);           break;
554         case DBTYPE_I1:          hr = VarUI1FromI1(*(signed char*)src, d);       break;
555         case DBTYPE_UI1:         *d = *(BYTE*)src; hr = S_OK;                    break;
556         case DBTYPE_UI2:         hr = VarUI1FromUI2(*(WORD*)src, d);             break;
557         case DBTYPE_UI4:         hr = VarUI1FromUI4(*(DWORD*)src, d);            break;
558         case DBTYPE_I8:          hr = VarUI1FromI8(*(LONGLONG*)src, d);          break;
559         case DBTYPE_UI8:         hr = VarUI1FromUI8(*(ULONGLONG*)src, d);        break;
560         default: FIXME("Unimplemented conversion %04x -> UI1\n", src_type); return E_NOTIMPL;
561         }
562         break;
563     }
564     case DBTYPE_UI2:
565     {
566         WORD *d = dst;
567         switch(src_type)
568         {
569         case DBTYPE_EMPTY:       *d = 0; hr = S_OK;                              break;
570         case DBTYPE_I2:          hr = VarUI2FromI2(*(signed short*)src, d);      break;
571         case DBTYPE_I4:          hr = VarUI2FromI4(*(signed int*)src, d);        break;
572         case DBTYPE_R4:          hr = VarUI2FromR4(*(FLOAT*)src, d);             break;
573         case DBTYPE_R8:          hr = VarUI2FromR8(*(double*)src, d);            break;
574         case DBTYPE_CY:          hr = VarUI2FromCy(*(CY*)src, d);                break;
575         case DBTYPE_DATE:        hr = VarUI2FromDate(*(DATE*)src, d);            break;
576         case DBTYPE_BSTR:        hr = VarUI2FromStr(*(WCHAR**)src, LOCALE_USER_DEFAULT, 0, d); break;
577         case DBTYPE_BOOL:        hr = VarUI2FromBool(*(VARIANT_BOOL*)src, d);    break;
578         case DBTYPE_DECIMAL:     hr = VarUI2FromDec((DECIMAL*)src, d);           break;
579         case DBTYPE_I1:          hr = VarUI2FromI1(*(signed char*)src, d);       break;
580         case DBTYPE_UI1:         hr = VarUI2FromUI1(*(BYTE*)src, d);             break;
581         case DBTYPE_UI2:         *d = *(WORD*)src; hr = S_OK;                     break;
582         case DBTYPE_UI4:         hr = VarUI2FromUI4(*(DWORD*)src, d);            break;
583         case DBTYPE_I8:          hr = VarUI2FromI8(*(LONGLONG*)src, d);          break;
584         case DBTYPE_UI8:         hr = VarUI2FromUI8(*(ULONGLONG*)src, d);        break;
585         default: FIXME("Unimplemented conversion %04x -> UI2\n", src_type); return E_NOTIMPL;
586         }
587         break;
588     }
589
590     case DBTYPE_UI4:
591     {
592         DWORD *d = dst;
593         switch(src_type)
594         {
595         case DBTYPE_EMPTY:       *d = 0; hr = S_OK;                              break;
596         case DBTYPE_I2:          hr = VarUI4FromI2(*(signed short*)src, d);      break;
597         case DBTYPE_I4:          hr = VarUI4FromI4(*(signed int*)src, d);        break;
598         case DBTYPE_R4:          hr = VarUI4FromR4(*(FLOAT*)src, d);             break;
599         case DBTYPE_R8:          hr = VarUI4FromR8(*(double*)src, d);            break;
600         case DBTYPE_CY:          hr = VarUI4FromCy(*(CY*)src, d);                break;
601         case DBTYPE_DATE:        hr = VarUI4FromDate(*(DATE*)src, d);            break;
602         case DBTYPE_BSTR:        hr = VarUI4FromStr(*(WCHAR**)src, LOCALE_USER_DEFAULT, 0, d); break;
603         case DBTYPE_BOOL:        hr = VarUI4FromBool(*(VARIANT_BOOL*)src, d);    break;
604         case DBTYPE_DECIMAL:     hr = VarUI4FromDec((DECIMAL*)src, d);           break;
605         case DBTYPE_I1:          hr = VarUI4FromI1(*(signed char*)src, d);       break;
606         case DBTYPE_UI1:         hr = VarUI4FromUI1(*(BYTE*)src, d);             break;
607         case DBTYPE_UI2:         hr = VarUI4FromUI2(*(WORD*)src, d);             break;
608         case DBTYPE_UI4:         *d = *(DWORD*)src; hr = S_OK;                   break;
609         case DBTYPE_I8:          hr = VarUI4FromI8(*(LONGLONG*)src, d);          break;
610         case DBTYPE_UI8:         hr = VarUI4FromUI8(*(ULONGLONG*)src, d);        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_I4:
756             V_VT(v) = VT_I4;
757             V_I4(v) = *(signed int*)src;
758             hr = S_OK;
759             break;
760         case DBTYPE_I8:
761             V_VT(v) = VT_DECIMAL;
762             hr = VarDecFromI8( *(LONGLONG*)src,  &V_DECIMAL(v));
763             break;
764         case DBTYPE_R8:
765             V_VT(v) = VT_R8;
766             V_R8(v) = *(double*)src;
767             hr = S_OK;
768             break;
769         case DBTYPE_BSTR:
770         {
771             BSTR s = *(WCHAR**)src;
772             TRACE("%s\n", debugstr_w(s));
773             V_VT(v) = VT_BSTR;
774             V_BSTR(v) = SysAllocString(s);
775             hr = V_BSTR(v) ? S_OK : E_OUTOFMEMORY;
776             break;
777         }
778         case DBTYPE_DATE:
779             V_VT(v) = VT_DATE;
780             V_DATE(v) = *(DATE*)src;
781             hr = S_OK;
782             break;
783         case DBTYPE_CY:
784             V_VT(v) = VT_CY;
785             V_CY(v) = *(CY*)src;
786             hr = S_OK;
787             break;
788         default: FIXME("Unimplemented conversion %04x -> VARIANT\n", src_type); return E_NOTIMPL;
789         }
790         break;
791     }
792
793     default:
794         FIXME("Unimplemented conversion %04x -> %04x\n", src_type, dst_type);
795         return E_NOTIMPL;
796     }
797
798     if(hr == DISP_E_OVERFLOW)
799     {
800         *dst_status = DBSTATUS_E_DATAOVERFLOW;
801         *dst_len = get_length(dst_type);
802         hr = DB_E_ERRORSOCCURRED;
803     }
804     else if(hr == S_OK)
805     {
806         *dst_status = DBSTATUS_S_OK;
807         *dst_len = get_length(dst_type);
808     }
809
810     return hr;
811 }
812
813 static inline WORD get_dbtype_class(DBTYPE type)
814 {
815     switch(type)
816     {
817     case DBTYPE_I2:
818     case DBTYPE_R4:
819     case DBTYPE_R8:
820     case DBTYPE_I1:
821     case DBTYPE_UI1:
822     case DBTYPE_UI2:
823         return DBTYPE_I2;
824
825     case DBTYPE_I4:
826     case DBTYPE_UI4:
827         return DBTYPE_I4;
828
829     case DBTYPE_I8:
830     case DBTYPE_UI8:
831         return DBTYPE_I8;
832
833     case DBTYPE_BSTR:
834     case DBTYPE_STR:
835     case DBTYPE_WSTR:
836         return DBTYPE_BSTR;
837
838     case DBTYPE_DBDATE:
839     case DBTYPE_DBTIME:
840     case DBTYPE_DBTIMESTAMP:
841         return DBTYPE_DBDATE;
842     }
843     return type;
844 }
845
846 /* Many src types will convert to this group of dst types */
847 static inline BOOL common_class(WORD dst_class)
848 {
849     switch(dst_class)
850     {
851     case DBTYPE_EMPTY:
852     case DBTYPE_NULL:
853     case DBTYPE_I2:
854     case DBTYPE_I4:
855     case DBTYPE_BSTR:
856     case DBTYPE_BOOL:
857     case DBTYPE_VARIANT:
858     case DBTYPE_I8:
859     case DBTYPE_CY:
860     case DBTYPE_DECIMAL:
861     case DBTYPE_NUMERIC:
862         return TRUE;
863     }
864     return FALSE;
865 }
866
867 static inline BOOL array_type(DBTYPE type)
868 {
869     return (type >= DBTYPE_I2 && type <= DBTYPE_UI4);
870 }
871
872 static HRESULT WINAPI convert_CanConvert(IDataConvert* iface,
873                                          DBTYPE src_type, DBTYPE dst_type)
874 {
875     convert *This = impl_from_IDataConvert(iface);
876     DBTYPE src_base_type = src_type & 0x1ff;
877     DBTYPE dst_base_type = dst_type & 0x1ff;
878     WORD dst_class = get_dbtype_class(dst_base_type);
879
880     TRACE("(%p)->(%d, %d)\n", This, src_type, dst_type);
881
882     if(src_type & DBTYPE_VECTOR || dst_type & DBTYPE_VECTOR) return S_FALSE;
883
884     if(src_type & DBTYPE_ARRAY)
885     {
886         if(!array_type(src_base_type)) return S_FALSE;
887         if(dst_type & DBTYPE_ARRAY)
888         {
889             if(src_type == dst_type) return S_OK;
890             return S_FALSE;
891         }
892         if(dst_type == DBTYPE_VARIANT) return S_OK;
893         return S_FALSE;
894     }
895
896     if(dst_type & DBTYPE_ARRAY)
897     {
898         if(!array_type(dst_base_type)) return S_FALSE;
899         if(src_type == DBTYPE_IDISPATCH || src_type == DBTYPE_VARIANT) return S_OK;
900         return S_FALSE;
901     }
902
903     if(dst_type & DBTYPE_BYREF)
904         if(dst_base_type != DBTYPE_BYTES && dst_base_type != DBTYPE_STR && dst_base_type != DBTYPE_WSTR)
905             return S_FALSE;
906
907     switch(get_dbtype_class(src_base_type))
908     {
909     case DBTYPE_EMPTY:
910         if(common_class(dst_class)) return S_OK;
911         switch(dst_class)
912         {
913         case DBTYPE_DATE:
914         case DBTYPE_GUID:
915         case DBTYPE_FILETIME:
916             return S_OK;
917         default:
918             if(dst_base_type == DBTYPE_DBTIMESTAMP) return S_OK;
919             return S_FALSE;
920         }
921
922     case DBTYPE_NULL:
923         switch(dst_base_type)
924         {
925         case DBTYPE_NULL:
926         case DBTYPE_VARIANT:
927         case DBTYPE_FILETIME: return S_OK;
928         default: return S_FALSE;
929         }
930
931     case DBTYPE_I4:
932         if(dst_base_type == DBTYPE_BYTES) return S_OK;
933         /* fall through */
934     case DBTYPE_I2:
935         if(dst_base_type == DBTYPE_DATE) return S_OK;
936         /* fall through */
937     case DBTYPE_DECIMAL:
938         if(common_class(dst_class)) return S_OK;
939         if(dst_class == DBTYPE_DBDATE) return S_OK;
940         return S_FALSE;
941
942     case DBTYPE_BOOL:
943         if(dst_base_type == DBTYPE_DATE) return S_OK;
944         /* fall through */
945     case DBTYPE_NUMERIC:
946     case DBTYPE_CY:
947         if(common_class(dst_class)) return S_OK;
948         return S_FALSE;
949
950     case DBTYPE_I8:
951         if(common_class(dst_class)) return S_OK;
952         switch(dst_base_type)
953         {
954         case DBTYPE_BYTES:
955         case DBTYPE_FILETIME: return S_OK;
956         default: return S_FALSE;
957         }
958
959     case DBTYPE_DATE:
960         switch(dst_class)
961         {
962         case DBTYPE_EMPTY:
963         case DBTYPE_NULL:
964         case DBTYPE_I2:
965         case DBTYPE_I4:
966         case DBTYPE_BSTR:
967         case DBTYPE_BOOL:
968         case DBTYPE_VARIANT:
969         case DBTYPE_I8:
970         case DBTYPE_DATE:
971         case DBTYPE_DBDATE:
972         case DBTYPE_FILETIME:
973             return S_OK;
974         default: return S_FALSE;
975         }
976
977     case DBTYPE_IDISPATCH:
978     case DBTYPE_VARIANT:
979         switch(dst_base_type)
980         {
981         case DBTYPE_IDISPATCH:
982         case DBTYPE_ERROR:
983         case DBTYPE_IUNKNOWN:
984             return S_OK;
985         }
986         /* fall through */
987     case DBTYPE_BSTR:
988         if(common_class(dst_class)) return S_OK;
989         switch(dst_class)
990         {
991         case DBTYPE_DATE:
992         case DBTYPE_GUID:
993         case DBTYPE_BYTES:
994         case DBTYPE_DBDATE:
995         case DBTYPE_FILETIME:
996             return S_OK;
997         default: return S_FALSE;
998         }
999
1000     case DBTYPE_ERROR:
1001         switch(dst_base_type)
1002         {
1003         case DBTYPE_BSTR:
1004         case DBTYPE_ERROR:
1005         case DBTYPE_VARIANT:
1006         case DBTYPE_WSTR:
1007             return S_OK;
1008         default: return S_FALSE;
1009         }
1010
1011     case DBTYPE_IUNKNOWN:
1012         switch(dst_base_type)
1013         {
1014         case DBTYPE_EMPTY:
1015         case DBTYPE_NULL:
1016         case DBTYPE_IDISPATCH:
1017         case DBTYPE_VARIANT:
1018         case DBTYPE_IUNKNOWN:
1019             return S_OK;
1020         default: return S_FALSE;
1021         }
1022
1023     case DBTYPE_BYTES:
1024         if(dst_class == DBTYPE_I4 || dst_class == DBTYPE_I8) return S_OK;
1025         /* fall through */
1026     case DBTYPE_GUID:
1027         switch(dst_class)
1028         {
1029         case DBTYPE_EMPTY:
1030         case DBTYPE_NULL:
1031         case DBTYPE_BSTR:
1032         case DBTYPE_VARIANT:
1033         case DBTYPE_GUID:
1034         case DBTYPE_BYTES:
1035             return S_OK;
1036         default: return S_FALSE;
1037         }
1038
1039     case DBTYPE_FILETIME:
1040         if(dst_class == DBTYPE_I8) return S_OK;
1041         /* fall through */
1042     case DBTYPE_DBDATE:
1043         switch(dst_class)
1044         {
1045         case DBTYPE_EMPTY:
1046         case DBTYPE_NULL:
1047         case DBTYPE_DATE:
1048         case DBTYPE_BSTR:
1049         case DBTYPE_VARIANT:
1050         case DBTYPE_DBDATE:
1051         case DBTYPE_FILETIME:
1052             return S_OK;
1053         default: return S_FALSE;
1054         }
1055
1056     }
1057     return S_FALSE;
1058 }
1059
1060 static HRESULT WINAPI convert_GetConversionSize(IDataConvert* iface,
1061                                                 DBTYPE src_type, DBTYPE dst_type,
1062                                                 DBLENGTH *src_len, DBLENGTH *dst_len,
1063                                                 void *src)
1064 {
1065     convert *This = impl_from_IDataConvert(iface);
1066     HRESULT hr;
1067
1068     TRACE("(%p)->(%d, %d, %p, %p, %p)\n", This, src_type, dst_type, src_len, dst_len, src);
1069
1070     hr = IDataConvert_CanConvert(iface, src_type, dst_type);
1071     if (hr != S_OK)
1072         return DB_E_UNSUPPORTEDCONVERSION;
1073
1074     if (!dst_len)
1075         return E_INVALIDARG;
1076
1077     /* for some types we don't need to look into source data */
1078     if ((*dst_len = get_length(dst_type)))
1079         return S_OK;
1080
1081     switch (dst_type)
1082     {
1083     case DBTYPE_STR:
1084     {
1085         switch (src_type)
1086         {
1087         case DBTYPE_VARIANT:
1088         {
1089             VARIANT v;
1090
1091             VariantInit(&v);
1092             if ((hr = VariantChangeType(&v, (VARIANT*)src, 0, VT_BSTR)) == S_OK)
1093             {
1094                 *dst_len = WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), -1, NULL, 0, NULL, NULL);
1095                 VariantClear(&v);
1096             }
1097             else
1098                 return hr;
1099         }
1100         break;
1101         default:
1102             FIXME("unimplemented for %04x -> DBTYPE_STR\n", src_type);
1103             return E_NOTIMPL;
1104         }
1105     }
1106     break;
1107     case DBTYPE_WSTR:
1108     {
1109         switch (src_type)
1110         {
1111         case DBTYPE_STR:
1112             if(src_len)
1113                 *dst_len = (*src_len + 1) * sizeof(WCHAR);
1114             else
1115                 *dst_len = (strlen(src) + 1) * sizeof(WCHAR);
1116             break;
1117         case DBTYPE_WSTR:
1118             if(src_len)
1119                 *dst_len = (*src_len) + sizeof(WCHAR);
1120             else
1121                 *dst_len = (lstrlenW(src) + 1) * sizeof(WCHAR);
1122             break;
1123         default:
1124             FIXME("unimplemented for %04x -> DBTYPE_WSTR\n", src_type);
1125             return E_NOTIMPL;
1126         }
1127     }
1128     break;
1129     default:
1130         FIXME("unimplemented for conversion %d->%d\n", src_type, dst_type);
1131         return E_NOTIMPL;
1132     }
1133
1134     return S_OK;
1135 }
1136
1137 static const struct IDataConvertVtbl convert_vtbl =
1138 {
1139     convert_QueryInterface,
1140     convert_AddRef,
1141     convert_Release,
1142     convert_DataConvert,
1143     convert_CanConvert,
1144     convert_GetConversionSize
1145 };
1146
1147 static HRESULT WINAPI dcinfo_QueryInterface(IDCInfo* iface, REFIID riid, void **obj)
1148 {
1149     convert *This = impl_from_IDCInfo(iface);
1150
1151     return IDataConvert_QueryInterface(&This->IDataConvert_iface, riid, obj);
1152 }
1153
1154 static ULONG WINAPI dcinfo_AddRef(IDCInfo* iface)
1155 {
1156     convert *This = impl_from_IDCInfo(iface);
1157
1158     return IDataConvert_AddRef(&This->IDataConvert_iface);
1159 }
1160
1161 static ULONG WINAPI dcinfo_Release(IDCInfo* iface)
1162 {
1163     convert *This = impl_from_IDCInfo(iface);
1164
1165     return IDataConvert_Release(&This->IDataConvert_iface);
1166 }
1167
1168 static HRESULT WINAPI dcinfo_GetInfo(IDCInfo *iface, ULONG num, DCINFOTYPE types[], DCINFO **info_ptr)
1169 {
1170     convert *This = impl_from_IDCInfo(iface);
1171     ULONG i;
1172     DCINFO *infos;
1173
1174     TRACE("(%p)->(%d, %p, %p)\n", This, num, types, info_ptr);
1175
1176     *info_ptr = infos = CoTaskMemAlloc(num * sizeof(*infos));
1177     if(!infos) return E_OUTOFMEMORY;
1178
1179     for(i = 0; i < num; i++)
1180     {
1181         infos[i].eInfoType = types[i];
1182         VariantInit(&infos[i].vData);
1183
1184         switch(types[i])
1185         {
1186         case DCINFOTYPE_VERSION:
1187             V_VT(&infos[i].vData) = VT_UI4;
1188             V_UI4(&infos[i].vData) = This->version;
1189             break;
1190         }
1191     }
1192
1193     return S_OK;
1194 }
1195
1196 static HRESULT WINAPI dcinfo_SetInfo(IDCInfo* iface, ULONG num, DCINFO info[])
1197 {
1198     convert *This = impl_from_IDCInfo(iface);
1199     ULONG i;
1200     HRESULT hr = S_OK;
1201
1202     TRACE("(%p)->(%d, %p)\n", This, num, info);
1203
1204     for(i = 0; i < num; i++)
1205     {
1206         switch(info[i].eInfoType)
1207         {
1208         case DCINFOTYPE_VERSION:
1209             if(V_VT(&info[i].vData) != VT_UI4)
1210             {
1211                 FIXME("VERSION with vt %x\n", V_VT(&info[i].vData));
1212                 hr = DB_S_ERRORSOCCURRED;
1213                 break;
1214             }
1215             This->version = V_UI4(&info[i].vData);
1216             break;
1217
1218         default:
1219             FIXME("Unhandled info type %d (vt %x)\n", info[i].eInfoType, V_VT(&info[i].vData));
1220         }
1221     }
1222     return hr;
1223 }
1224
1225 static const struct IDCInfoVtbl dcinfo_vtbl =
1226 {
1227     dcinfo_QueryInterface,
1228     dcinfo_AddRef,
1229     dcinfo_Release,
1230     dcinfo_GetInfo,
1231     dcinfo_SetInfo
1232 };
1233
1234 HRESULT create_oledb_convert(IUnknown *outer, void **obj)
1235 {
1236     convert *This;
1237
1238     TRACE("(%p, %p)\n", outer, obj);
1239
1240     *obj = NULL;
1241
1242     if(outer) return CLASS_E_NOAGGREGATION;
1243
1244     This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1245     if(!This) return E_OUTOFMEMORY;
1246
1247     This->IDataConvert_iface.lpVtbl = &convert_vtbl;
1248     This->IDCInfo_iface.lpVtbl = &dcinfo_vtbl;
1249     This->ref = 1;
1250     This->version = 0x110;
1251
1252     *obj = &This->IDataConvert_iface;
1253
1254     return S_OK;
1255 }