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