comctl32: Fix compiler warnings with flag -Wcast-qual.
[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_BYREF | DBTYPE_WSTR:
140         return 0;
141     default:
142         FIXME("Unhandled type %04x\n", type);
143         return 0;
144     }
145 }
146
147 static HRESULT WINAPI convert_DataConvert(IDataConvert* iface,
148                                           DBTYPE src_type, DBTYPE dst_type,
149                                           DBLENGTH src_len, DBLENGTH *dst_len,
150                                           void *src, void *dst,
151                                           DBLENGTH dst_max_len,
152                                           DBSTATUS src_status, DBSTATUS *dst_status,
153                                           BYTE precision, BYTE scale,
154                                           DBDATACONVERT flags)
155 {
156     convert *This = impl_from_IDataConvert(iface);
157     HRESULT hr;
158
159     TRACE("(%p)->(%d, %d, %d, %p, %p, %p, %d, %d, %p, %d, %d, %x)\n", This,
160           src_type, dst_type, src_len, dst_len, src, dst, dst_max_len,
161           src_status, dst_status, precision, scale, flags);
162
163     *dst_len = get_length(dst_type);
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         switch(src_type)
217         {
218         case DBTYPE_EMPTY:       *d = 0; hr = S_OK;                              break;
219         case DBTYPE_I2:          *d = *(signed short*)src; hr = S_OK;            break;
220         case DBTYPE_I4:          hr = VarI2FromI4(*(signed int*)src, d);         break;
221         case DBTYPE_R4:          hr = VarI2FromR4(*(FLOAT*)src, d);              break;
222         case DBTYPE_R8:          hr = VarI2FromR8(*(double*)src, d);             break;
223         case DBTYPE_CY:          hr = VarI2FromCy(*(CY*)src, d);                 break;
224         case DBTYPE_DATE:        hr = VarI2FromDate(*(DATE*)src, d);             break;
225         case DBTYPE_BSTR:        hr = VarI2FromStr(*(WCHAR**)src, LOCALE_USER_DEFAULT, 0, d); break;
226         case DBTYPE_BOOL:        hr = VarI2FromBool(*(VARIANT_BOOL*)src, d);     break;
227         case DBTYPE_DECIMAL:     hr = VarI2FromDec((DECIMAL*)src, d);            break;
228         case DBTYPE_I1:          hr = VarI2FromI1(*(signed char*)src, d);        break;
229         case DBTYPE_UI1:         hr = VarI2FromUI1(*(BYTE*)src, d);              break;
230         case DBTYPE_UI2:         hr = VarI2FromUI2(*(WORD*)src, d);              break;
231         case DBTYPE_UI4:         hr = VarI2FromUI4(*(DWORD*)src, d);             break;
232         case DBTYPE_I8:          hr = VarI2FromI8(*(LONGLONG*)src, d);           break;
233         case DBTYPE_UI8:         hr = VarI2FromUI8(*(ULONGLONG*)src, d);         break;
234         default: FIXME("Unimplemented conversion %04x -> I2\n", src_type); return E_NOTIMPL;
235         }
236         break;
237     }
238
239     case DBTYPE_I4:
240     {
241         signed int *d = dst;
242         switch(src_type)
243         {
244         case DBTYPE_EMPTY:       *d = 0; hr = S_OK;                              break;
245         case DBTYPE_I2:          hr = VarI4FromI2(*(signed short*)src, d);       break;
246         case DBTYPE_I4:          *d = *(signed int*)src; hr = S_OK;              break;
247         case DBTYPE_R4:          hr = VarI4FromR4(*(FLOAT*)src, d);              break;
248         case DBTYPE_R8:          hr = VarI4FromR8(*(double*)src, d);             break;
249         case DBTYPE_CY:          hr = VarI4FromCy(*(CY*)src, d);                 break;
250         case DBTYPE_DATE:        hr = VarI4FromDate(*(DATE*)src, d);             break;
251         case DBTYPE_BSTR:        hr = VarI4FromStr(*(WCHAR**)src, LOCALE_USER_DEFAULT, 0, d); break;
252         case DBTYPE_BOOL:        hr = VarI4FromBool(*(VARIANT_BOOL*)src, d);     break;
253         case DBTYPE_DECIMAL:     hr = VarI4FromDec((DECIMAL*)src, d);            break;
254         case DBTYPE_I1:          hr = VarI4FromI1(*(signed char*)src, d);        break;
255         case DBTYPE_UI1:         hr = VarI4FromUI1(*(BYTE*)src, d);              break;
256         case DBTYPE_UI2:         hr = VarI4FromUI2(*(WORD*)src, d);              break;
257         case DBTYPE_UI4:         hr = VarI4FromUI4(*(DWORD*)src, d);             break;
258         case DBTYPE_I8:          hr = VarI4FromI8(*(LONGLONG*)src, d);           break;
259         case DBTYPE_UI8:         hr = VarI4FromUI8(*(ULONGLONG*)src, d);         break;
260         default: FIXME("Unimplemented conversion %04x -> I4\n", src_type); return E_NOTIMPL;
261         }
262         break;
263     }
264
265     case DBTYPE_R4:
266     {
267         FLOAT *d = dst;
268         switch(src_type)
269         {
270         case DBTYPE_EMPTY:       *d = 0; hr = S_OK;                              break;
271         case DBTYPE_I2:          hr = VarR4FromI2(*(signed short*)src, d);       break;
272         case DBTYPE_I4:          hr = VarR4FromI4(*(signed int*)src, d);         break;
273         case DBTYPE_R4:          *d = *(FLOAT*)src; hr = S_OK;                   break;
274         case DBTYPE_R8:          hr = VarR4FromR8(*(double*)src, d);             break;
275         case DBTYPE_CY:          hr = VarR4FromCy(*(CY*)src, d);                 break;
276         case DBTYPE_DATE:        hr = VarR4FromDate(*(DATE*)src, d);             break;
277         case DBTYPE_BSTR:        hr = VarR4FromStr(*(WCHAR**)src, LOCALE_USER_DEFAULT, 0, d); break;
278         case DBTYPE_BOOL:        hr = VarR4FromBool(*(VARIANT_BOOL*)src, d);     break;
279         case DBTYPE_DECIMAL:     hr = VarR4FromDec((DECIMAL*)src, d);            break;
280         case DBTYPE_I1:          hr = VarR4FromI1(*(signed char*)src, d);        break;
281         case DBTYPE_UI1:         hr = VarR4FromUI1(*(BYTE*)src, d);              break;
282         case DBTYPE_UI2:         hr = VarR4FromUI2(*(WORD*)src, d);              break;
283         case DBTYPE_UI4:         hr = VarR4FromUI4(*(DWORD*)src, d);             break;
284         case DBTYPE_I8:          hr = VarR4FromI8(*(LONGLONG*)src, d);           break;
285         case DBTYPE_UI8:         hr = VarR4FromUI8(*(ULONGLONG*)src, d);         break;
286         default: FIXME("Unimplemented conversion %04x -> R4\n", src_type); return E_NOTIMPL;
287         }
288         break;
289     }
290
291     case DBTYPE_CY:
292     {
293         CY *d = dst;
294         switch(src_type)
295         {
296         case DBTYPE_EMPTY:       d->int64 = 0; hr = S_OK;                              break;
297         case DBTYPE_I2:          hr = VarCyFromI2(*(signed short*)src, d);       break;
298         case DBTYPE_I4:          hr = VarCyFromI4(*(signed int*)src, d);         break;
299         case DBTYPE_R4:          hr = VarCyFromR4(*(FLOAT*)src, d);              break;
300         case DBTYPE_R8:          hr = VarCyFromR8(*(double*)src, d);             break;
301         case DBTYPE_CY:          *d = *(CY*)src; hr = S_OK;                      break;
302         case DBTYPE_DATE:        hr = VarCyFromDate(*(DATE*)src, d);             break;
303         case DBTYPE_BSTR:        hr = VarCyFromStr(*(WCHAR**)src, LOCALE_USER_DEFAULT, 0, d); break;
304         case DBTYPE_BOOL:        hr = VarCyFromBool(*(VARIANT_BOOL*)src, d);     break;
305         case DBTYPE_DECIMAL:     hr = VarCyFromDec((DECIMAL*)src, d);            break;
306         case DBTYPE_I1:          hr = VarCyFromI1(*(signed char*)src, d);        break;
307         case DBTYPE_UI1:         hr = VarCyFromUI1(*(BYTE*)src, d);              break;
308         case DBTYPE_UI2:         hr = VarCyFromUI2(*(WORD*)src, d);              break;
309         case DBTYPE_UI4:         hr = VarCyFromUI4(*(DWORD*)src, d);             break;
310         case DBTYPE_I8:          hr = VarCyFromI8(*(LONGLONG*)src, d);           break;
311         case DBTYPE_UI8:         hr = VarCyFromUI8(*(ULONGLONG*)src, d);         break;
312         default: FIXME("Unimplemented conversion %04x -> CY\n", src_type); return E_NOTIMPL;
313         }
314         break;
315     }
316
317     case DBTYPE_BSTR:
318     {
319         BSTR *d = dst;
320         switch(src_type)
321         {
322         case DBTYPE_EMPTY:       *d = SysAllocStringLen(NULL, 0); hr = *d ? S_OK : E_OUTOFMEMORY;      break;
323         case DBTYPE_I2:          hr = VarBstrFromI2(*(signed short*)src, LOCALE_USER_DEFAULT, 0, d);   break;
324         case DBTYPE_I4:          hr = VarBstrFromI4(*(signed int*)src, LOCALE_USER_DEFAULT, 0, d);     break;
325         case DBTYPE_R4:          hr = VarBstrFromR4(*(FLOAT*)src, LOCALE_USER_DEFAULT, 0, d);          break;
326         case DBTYPE_R8:          hr = VarBstrFromR8(*(double*)src, LOCALE_USER_DEFAULT, 0, d);         break;
327         case DBTYPE_CY:          hr = VarBstrFromCy(*(CY*)src, LOCALE_USER_DEFAULT, 0, d);             break;
328         case DBTYPE_DATE:        hr = VarBstrFromDate(*(DATE*)src, LOCALE_USER_DEFAULT, 0, d);         break;
329         case DBTYPE_BSTR:        *d = SysAllocStringLen(*(BSTR*)src, SysStringLen(*(BSTR*)src)); hr = *d ? S_OK : E_OUTOFMEMORY;     break;
330         case DBTYPE_BOOL:        hr = VarBstrFromBool(*(VARIANT_BOOL*)src, LOCALE_USER_DEFAULT, 0, d); break;
331         case DBTYPE_DECIMAL:     hr = VarBstrFromDec((DECIMAL*)src, LOCALE_USER_DEFAULT, 0, d);        break;
332         case DBTYPE_I1:          hr = VarBstrFromI1(*(signed char*)src, LOCALE_USER_DEFAULT, 0, d);    break;
333         case DBTYPE_UI1:         hr = VarBstrFromUI1(*(BYTE*)src, LOCALE_USER_DEFAULT, 0, d);          break;
334         case DBTYPE_UI2:         hr = VarBstrFromUI2(*(WORD*)src, LOCALE_USER_DEFAULT, 0, d);          break;
335         case DBTYPE_UI4:         hr = VarBstrFromUI4(*(DWORD*)src, LOCALE_USER_DEFAULT, 0, d);         break;
336         case DBTYPE_I8:          hr = VarBstrFromI8(*(LONGLONG*)src, LOCALE_USER_DEFAULT, 0, d);       break;
337         case DBTYPE_UI8:         hr = VarBstrFromUI8(*(ULONGLONG*)src, LOCALE_USER_DEFAULT, 0, d);     break;
338         default: FIXME("Unimplemented conversion %04x -> BSTR\n", src_type); return E_NOTIMPL;
339         }
340         break;
341     }
342
343     case DBTYPE_UI1:
344     {
345         BYTE *d = dst;
346         switch(src_type)
347         {
348         case DBTYPE_EMPTY:       *d = 0; hr = S_OK;                              break;
349         case DBTYPE_I2:          hr = VarUI1FromI2(*(signed short*)src, d);      break;
350         case DBTYPE_I4:          hr = VarUI1FromI4(*(signed int*)src, d);        break;
351         case DBTYPE_R4:          hr = VarUI1FromR4(*(FLOAT*)src, d);             break;
352         case DBTYPE_R8:          hr = VarUI1FromR8(*(double*)src, d);            break;
353         case DBTYPE_CY:          hr = VarUI1FromCy(*(CY*)src, d);                break;
354         case DBTYPE_DATE:        hr = VarUI1FromDate(*(DATE*)src, d);            break;
355         case DBTYPE_BSTR:        hr = VarUI1FromStr(*(WCHAR**)src, LOCALE_USER_DEFAULT, 0, d); break;
356         case DBTYPE_BOOL:        hr = VarUI1FromBool(*(VARIANT_BOOL*)src, d);    break;
357         case DBTYPE_DECIMAL:     hr = VarUI1FromDec((DECIMAL*)src, d);           break;
358         case DBTYPE_I1:          hr = VarUI1FromI1(*(signed char*)src, d);       break;
359         case DBTYPE_UI1:         *d = *(BYTE*)src; hr = S_OK;                    break;
360         case DBTYPE_UI2:         hr = VarUI1FromUI2(*(WORD*)src, d);             break;
361         case DBTYPE_UI4:         hr = VarUI1FromUI4(*(DWORD*)src, d);            break;
362         case DBTYPE_I8:          hr = VarUI1FromI8(*(LONGLONG*)src, d);          break;
363         case DBTYPE_UI8:         hr = VarUI1FromUI8(*(ULONGLONG*)src, d);        break;
364         default: FIXME("Unimplemented conversion %04x -> UI1\n", src_type); return E_NOTIMPL;
365         }
366         break;
367     }
368
369     case DBTYPE_UI4:
370     {
371         DWORD *d = dst;
372         switch(src_type)
373         {
374         case DBTYPE_EMPTY:       *d = 0; hr = S_OK;                              break;
375         case DBTYPE_I2:          hr = VarUI4FromI2(*(signed short*)src, d);      break;
376         case DBTYPE_I4:          hr = VarUI4FromI4(*(signed int*)src, d);        break;
377         case DBTYPE_R4:          hr = VarUI4FromR4(*(FLOAT*)src, d);             break;
378         case DBTYPE_R8:          hr = VarUI4FromR8(*(double*)src, d);            break;
379         case DBTYPE_CY:          hr = VarUI4FromCy(*(CY*)src, d);                break;
380         case DBTYPE_DATE:        hr = VarUI4FromDate(*(DATE*)src, d);            break;
381         case DBTYPE_BSTR:        hr = VarUI4FromStr(*(WCHAR**)src, LOCALE_USER_DEFAULT, 0, d); break;
382         case DBTYPE_BOOL:        hr = VarUI4FromBool(*(VARIANT_BOOL*)src, d);    break;
383         case DBTYPE_DECIMAL:     hr = VarUI4FromDec((DECIMAL*)src, d);           break;
384         case DBTYPE_I1:          hr = VarUI4FromI1(*(signed char*)src, d);       break;
385         case DBTYPE_UI1:         hr = VarUI4FromUI1(*(BYTE*)src, d);             break;
386         case DBTYPE_UI2:         hr = VarUI4FromUI2(*(WORD*)src, d);             break;
387         case DBTYPE_UI4:         *d = *(DWORD*)src; hr = S_OK;                   break;
388         case DBTYPE_I8:          hr = VarUI4FromI8(*(LONGLONG*)src, d);          break;
389         case DBTYPE_UI8:         hr = VarUI4FromUI8(*(ULONGLONG*)src, d);        break;
390         default: FIXME("Unimplemented conversion %04x -> UI4\n", src_type); return E_NOTIMPL;
391         }
392         break;
393     }
394
395     case DBTYPE_UI8:
396     {
397         ULONGLONG *d = dst;
398         switch(src_type)
399         {
400         case DBTYPE_EMPTY:       *d = 0; hr = S_OK;                              break;
401         case DBTYPE_I2:          hr = VarUI8FromI2(*(signed short*)src, d);      break;
402         case DBTYPE_I4:          {LONGLONG s = *(signed int*)src; hr = VarUI8FromI8(s, d);        break;}
403         case DBTYPE_R4:          hr = VarUI8FromR4(*(FLOAT*)src, d);             break;
404         case DBTYPE_R8:          hr = VarUI8FromR8(*(double*)src, d);            break;
405         case DBTYPE_CY:          hr = VarUI8FromCy(*(CY*)src, d);                break;
406         case DBTYPE_DATE:        hr = VarUI8FromDate(*(DATE*)src, d);            break;
407         case DBTYPE_BSTR:        hr = VarUI8FromStr(*(WCHAR**)src, LOCALE_USER_DEFAULT, 0, d); break;
408         case DBTYPE_BOOL:        hr = VarUI8FromBool(*(VARIANT_BOOL*)src, d);    break;
409         case DBTYPE_DECIMAL:     hr = VarUI8FromDec((DECIMAL*)src, d);           break;
410         case DBTYPE_I1:          hr = VarUI8FromI1(*(signed char*)src, d);       break;
411         case DBTYPE_UI1:         hr = VarUI8FromUI1(*(BYTE*)src, d);             break;
412         case DBTYPE_UI2:         hr = VarUI8FromUI2(*(WORD*)src, d);             break;
413         case DBTYPE_UI4:         hr = VarUI8FromUI4(*(DWORD*)src, d);            break;
414         case DBTYPE_I8:          hr = VarUI8FromI8(*(LONGLONG*)src, d);          break;
415         case DBTYPE_UI8:         *d = *(ULONGLONG*)src; hr = S_OK;               break;
416         default: FIXME("Unimplemented conversion %04x -> UI8\n", src_type); return E_NOTIMPL;
417         }
418         break;
419     }
420
421     case DBTYPE_FILETIME:
422     {
423         FILETIME *d = dst;
424         switch(src_type)
425         {
426         case DBTYPE_EMPTY:       d->dwLowDateTime = d->dwHighDateTime = 0; hr = S_OK;    break;
427         case DBTYPE_FILETIME:    *d = *(FILETIME*)src; hr = S_OK;                        break;
428         default: FIXME("Unimplemented conversion %04x -> FILETIME\n", src_type); return E_NOTIMPL;
429         }
430         break;
431     }
432
433     case DBTYPE_GUID:
434     {
435         GUID *d = dst;
436         switch(src_type)
437         {
438         case DBTYPE_EMPTY:       *d = GUID_NULL; hr = S_OK; break;
439         case DBTYPE_GUID:        *d = *(GUID*)src; hr = S_OK; break;
440         default: FIXME("Unimplemented conversion %04x -> GUID\n", src_type); return E_NOTIMPL;
441         }
442         break;
443     }
444
445     case DBTYPE_WSTR:
446     {
447         BSTR b;
448         DBLENGTH bstr_len;
449         INT bytes_to_copy;
450         hr = IDataConvert_DataConvert(iface, src_type, DBTYPE_BSTR, src_len, &bstr_len,
451                                       src, &b, sizeof(BSTR), src_status, dst_status,
452                                       precision, scale, flags);
453         if(hr != S_OK) return hr;
454         bstr_len = SysStringLen(b);
455         *dst_len = bstr_len * sizeof(WCHAR); /* Doesn't include size for '\0' */
456         *dst_status = DBSTATUS_S_OK;
457         bytes_to_copy = min(*dst_len + sizeof(WCHAR), dst_max_len);
458         if(dst)
459         {
460             if(bytes_to_copy >= sizeof(WCHAR))
461             {
462                 memcpy(dst, b, bytes_to_copy - sizeof(WCHAR));
463                 *((WCHAR*)dst + bytes_to_copy / sizeof(WCHAR) - 1) = 0;
464                 if(bytes_to_copy < *dst_len + sizeof(WCHAR))
465                     *dst_status = DBSTATUS_S_TRUNCATED;
466             }
467             else
468             {
469                 *dst_status = DBSTATUS_E_DATAOVERFLOW;
470                 hr = DB_E_ERRORSOCCURRED;
471             }
472         }
473         SysFreeString(b);
474         return hr;
475     }
476
477     case DBTYPE_BYREF | DBTYPE_WSTR:
478     {
479         BSTR b;
480         WCHAR **d = dst;
481         DBLENGTH bstr_len;
482         hr = IDataConvert_DataConvert(iface, src_type, DBTYPE_BSTR, src_len, &bstr_len,
483                                       src, &b, sizeof(BSTR), src_status, dst_status,
484                                       precision, scale, flags);
485         if(hr != S_OK) return hr;
486
487         bstr_len = SysStringLen(b) * sizeof(WCHAR);
488         *dst_len = bstr_len; /* Doesn't include size for '\0' */
489
490         *d = CoTaskMemAlloc(bstr_len + sizeof(WCHAR));
491         if(*d) memcpy(*d, b, bstr_len + sizeof(WCHAR));
492         else hr = E_OUTOFMEMORY;
493         SysFreeString(b);
494         return hr;
495     }
496
497     default:
498         FIXME("Unimplemented conversion %04x -> %04x\n", src_type, dst_type);
499         return E_NOTIMPL;
500
501     }
502
503     if(hr == DISP_E_OVERFLOW)
504     {
505         *dst_status = DBSTATUS_E_DATAOVERFLOW;
506         hr = DB_E_ERRORSOCCURRED;
507     }
508     else if(hr == S_OK)
509         *dst_status = DBSTATUS_S_OK;
510
511     return hr;
512 }
513
514 static inline WORD get_dbtype_class(DBTYPE type)
515 {
516     switch(type)
517     {
518     case DBTYPE_I2:
519     case DBTYPE_R4:
520     case DBTYPE_R8:
521     case DBTYPE_I1:
522     case DBTYPE_UI1:
523     case DBTYPE_UI2:
524         return DBTYPE_I2;
525
526     case DBTYPE_I4:
527     case DBTYPE_UI4:
528         return DBTYPE_I4;
529
530     case DBTYPE_I8:
531     case DBTYPE_UI8:
532         return DBTYPE_I8;
533
534     case DBTYPE_BSTR:
535     case DBTYPE_STR:
536     case DBTYPE_WSTR:
537         return DBTYPE_BSTR;
538
539     case DBTYPE_DBDATE:
540     case DBTYPE_DBTIME:
541     case DBTYPE_DBTIMESTAMP:
542         return DBTYPE_DBDATE;
543     }
544     return type;
545 }
546
547 /* Many src types will convert to this group of dst types */
548 static inline BOOL common_class(WORD dst_class)
549 {
550     switch(dst_class)
551     {
552     case DBTYPE_EMPTY:
553     case DBTYPE_NULL:
554     case DBTYPE_I2:
555     case DBTYPE_I4:
556     case DBTYPE_BSTR:
557     case DBTYPE_BOOL:
558     case DBTYPE_VARIANT:
559     case DBTYPE_I8:
560     case DBTYPE_CY:
561     case DBTYPE_DECIMAL:
562     case DBTYPE_NUMERIC:
563         return TRUE;
564     }
565     return FALSE;
566 }
567
568 static inline BOOL array_type(DBTYPE type)
569 {
570     return (type >= DBTYPE_I2 && type <= DBTYPE_UI4);
571 }
572
573 static HRESULT WINAPI convert_CanConvert(IDataConvert* iface,
574                                          DBTYPE src_type, DBTYPE dst_type)
575 {
576     convert *This = impl_from_IDataConvert(iface);
577     DBTYPE src_base_type = src_type & 0x1ff;
578     DBTYPE dst_base_type = dst_type & 0x1ff;
579     WORD dst_class = get_dbtype_class(dst_base_type);
580
581     TRACE("(%p)->(%d, %d)\n", This, src_type, dst_type);
582
583     if(src_type & DBTYPE_VECTOR || dst_type & DBTYPE_VECTOR) return S_FALSE;
584
585     if(src_type & DBTYPE_ARRAY)
586     {
587         if(!array_type(src_base_type)) return S_FALSE;
588         if(dst_type & DBTYPE_ARRAY)
589         {
590             if(src_type == dst_type) return S_OK;
591             return S_FALSE;
592         }
593         if(dst_type == DBTYPE_VARIANT) return S_OK;
594         return S_FALSE;
595     }
596
597     if(dst_type & DBTYPE_ARRAY)
598     {
599         if(!array_type(dst_base_type)) return S_FALSE;
600         if(src_type == DBTYPE_IDISPATCH || src_type == DBTYPE_VARIANT) return S_OK;
601         return S_FALSE;
602     }
603
604     if(dst_type & DBTYPE_BYREF)
605         if(dst_base_type != DBTYPE_BYTES && dst_base_type != DBTYPE_STR && dst_base_type != DBTYPE_WSTR)
606             return S_FALSE;
607
608     switch(get_dbtype_class(src_base_type))
609     {
610     case DBTYPE_EMPTY:
611         if(common_class(dst_class)) return S_OK;
612         switch(dst_class)
613         {
614         case DBTYPE_DATE:
615         case DBTYPE_GUID:
616         case DBTYPE_FILETIME:
617             return S_OK;
618         default:
619             if(dst_base_type == DBTYPE_DBTIMESTAMP) return S_OK;
620             return S_FALSE;
621         }
622
623     case DBTYPE_NULL:
624         switch(dst_base_type)
625         {
626         case DBTYPE_NULL:
627         case DBTYPE_VARIANT:
628         case DBTYPE_FILETIME: return S_OK;
629         default: return S_FALSE;
630         }
631
632     case DBTYPE_I4:
633         if(dst_base_type == DBTYPE_BYTES) return S_OK;
634         /* fall through */
635     case DBTYPE_I2:
636         if(dst_base_type == DBTYPE_DATE) return S_OK;
637         /* fall through */
638     case DBTYPE_DECIMAL:
639         if(common_class(dst_class)) return S_OK;
640         if(dst_class == DBTYPE_DBDATE) return S_OK;
641         return S_FALSE;
642
643     case DBTYPE_BOOL:
644         if(dst_base_type == DBTYPE_DATE) return S_OK;
645     case DBTYPE_NUMERIC:
646     case DBTYPE_CY:
647         if(common_class(dst_class)) return S_OK;
648         return S_FALSE;
649
650     case DBTYPE_I8:
651         if(common_class(dst_class)) return S_OK;
652         switch(dst_base_type)
653         {
654         case DBTYPE_BYTES:
655         case DBTYPE_FILETIME: return S_OK;
656         default: return S_FALSE;
657         }
658
659     case DBTYPE_DATE:
660         switch(dst_class)
661         {
662         case DBTYPE_EMPTY:
663         case DBTYPE_NULL:
664         case DBTYPE_I2:
665         case DBTYPE_I4:
666         case DBTYPE_BSTR:
667         case DBTYPE_BOOL:
668         case DBTYPE_VARIANT:
669         case DBTYPE_I8:
670         case DBTYPE_DATE:
671         case DBTYPE_DBDATE:
672         case DBTYPE_FILETIME:
673             return S_OK;
674         default: return S_FALSE;
675         }
676
677     case DBTYPE_IDISPATCH:
678     case DBTYPE_VARIANT:
679         switch(dst_base_type)
680         {
681         case DBTYPE_IDISPATCH:
682         case DBTYPE_ERROR:
683         case DBTYPE_IUNKNOWN:
684             return S_OK;
685         }
686         /* fall through */
687     case DBTYPE_BSTR:
688         if(common_class(dst_class)) return S_OK;
689         switch(dst_class)
690         {
691         case DBTYPE_DATE:
692         case DBTYPE_GUID:
693         case DBTYPE_BYTES:
694         case DBTYPE_DBDATE:
695         case DBTYPE_FILETIME:
696             return S_OK;
697         default: return S_FALSE;
698         }
699
700     case DBTYPE_ERROR:
701         switch(dst_base_type)
702         {
703         case DBTYPE_BSTR:
704         case DBTYPE_ERROR:
705         case DBTYPE_VARIANT:
706         case DBTYPE_WSTR:
707             return S_OK;
708         default: return S_FALSE;
709         }
710
711     case DBTYPE_IUNKNOWN:
712         switch(dst_base_type)
713         {
714         case DBTYPE_EMPTY:
715         case DBTYPE_NULL:
716         case DBTYPE_IDISPATCH:
717         case DBTYPE_VARIANT:
718         case DBTYPE_IUNKNOWN:
719             return S_OK;
720         default: return S_FALSE;
721         }
722
723     case DBTYPE_BYTES:
724         if(dst_class == DBTYPE_I4 || dst_class == DBTYPE_I8) return S_OK;
725         /* fall through */
726     case DBTYPE_GUID:
727         switch(dst_class)
728         {
729         case DBTYPE_EMPTY:
730         case DBTYPE_NULL:
731         case DBTYPE_BSTR:
732         case DBTYPE_VARIANT:
733         case DBTYPE_GUID:
734         case DBTYPE_BYTES:
735             return S_OK;
736         default: return S_FALSE;
737         }
738
739     case DBTYPE_FILETIME:
740         if(dst_class == DBTYPE_I8) return S_OK;
741         /* fall through */
742     case DBTYPE_DBDATE:
743         switch(dst_class)
744         {
745         case DBTYPE_EMPTY:
746         case DBTYPE_NULL:
747         case DBTYPE_DATE:
748         case DBTYPE_BSTR:
749         case DBTYPE_VARIANT:
750         case DBTYPE_DBDATE:
751         case DBTYPE_FILETIME:
752             return S_OK;
753         default: return S_FALSE;
754         }
755
756     }
757     return S_FALSE;
758 }
759
760 static HRESULT WINAPI convert_GetConversionSize(IDataConvert* iface,
761                                                 DBTYPE wSrcType, DBTYPE wDstType,
762                                                 DBLENGTH *pcbSrcLength, DBLENGTH *pcbDstLength,
763                                                 void *pSrc)
764 {
765     convert *This = impl_from_IDataConvert(iface);
766     FIXME("(%p)->(%d, %d, %p, %p, %p): stub\n", This, wSrcType, wDstType, pcbSrcLength, pcbDstLength, pSrc);
767
768     return E_NOTIMPL;
769 }
770
771 static const struct IDataConvertVtbl convert_vtbl =
772 {
773     convert_QueryInterface,
774     convert_AddRef,
775     convert_Release,
776     convert_DataConvert,
777     convert_CanConvert,
778     convert_GetConversionSize
779 };
780
781 static HRESULT WINAPI dcinfo_QueryInterface(IDCInfo* iface, REFIID riid, void **obj)
782 {
783     convert *This = impl_from_IDCInfo(iface);
784
785     return IDataConvert_QueryInterface((IDataConvert *)This, riid, obj);
786 }
787
788 static ULONG WINAPI dcinfo_AddRef(IDCInfo* iface)
789 {
790     convert *This = impl_from_IDCInfo(iface);
791
792     return IDataConvert_AddRef((IDataConvert *)This);
793 }
794
795 static ULONG WINAPI dcinfo_Release(IDCInfo* iface)
796 {
797     convert *This = impl_from_IDCInfo(iface);
798
799     return IDataConvert_Release((IDataConvert *)This);
800 }
801
802 static HRESULT WINAPI dcinfo_GetInfo(IDCInfo *iface, ULONG num, DCINFOTYPE types[], DCINFO **info_ptr)
803 {
804     convert *This = impl_from_IDCInfo(iface);
805     ULONG i;
806     DCINFO *infos;
807
808     TRACE("(%p)->(%d, %p, %p)\n", This, num, types, info_ptr);
809
810     *info_ptr = infos = CoTaskMemAlloc(num * sizeof(*infos));
811     if(!infos) return E_OUTOFMEMORY;
812
813     for(i = 0; i < num; i++)
814     {
815         infos[i].eInfoType = types[i];
816         VariantInit(&infos[i].vData);
817
818         switch(types[i])
819         {
820         case DCINFOTYPE_VERSION:
821             V_VT(&infos[i].vData) = VT_UI4;
822             V_UI4(&infos[i].vData) = This->version;
823             break;
824         }
825     }
826
827     return S_OK;
828 }
829
830 static HRESULT WINAPI dcinfo_SetInfo(IDCInfo* iface, ULONG num, DCINFO info[])
831 {
832     convert *This = impl_from_IDCInfo(iface);
833     ULONG i;
834     HRESULT hr = S_OK;
835
836     TRACE("(%p)->(%d, %p)\n", This, num, info);
837
838     for(i = 0; i < num; i++)
839     {
840         switch(info[i].eInfoType)
841         {
842         case DCINFOTYPE_VERSION:
843             if(V_VT(&info[i].vData) != VT_UI4)
844             {
845                 FIXME("VERSION with vt %x\n", V_VT(&info[i].vData));
846                 hr = DB_S_ERRORSOCCURRED;
847                 break;
848             }
849             This->version = V_UI4(&info[i].vData);
850             break;
851
852         default:
853             FIXME("Unhandled info type %d (vt %x)\n", info[i].eInfoType, V_VT(&info[i].vData));
854         }
855     }
856     return hr;
857 }
858
859 static const struct IDCInfoVtbl dcinfo_vtbl =
860 {
861     dcinfo_QueryInterface,
862     dcinfo_AddRef,
863     dcinfo_Release,
864     dcinfo_GetInfo,
865     dcinfo_SetInfo
866 };
867
868 HRESULT create_oledb_convert(IUnknown *outer, void **obj)
869 {
870     convert *This;
871
872     TRACE("(%p, %p)\n", outer, obj);
873
874     *obj = NULL;
875
876     if(outer) return CLASS_E_NOAGGREGATION;
877
878     This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
879     if(!This) return E_OUTOFMEMORY;
880
881     This->lpVtbl = &convert_vtbl;
882     This->lpDCInfoVtbl = &dcinfo_vtbl;
883     This->ref = 1;
884     This->version = 0x110;
885
886     *obj = &This->lpVtbl;
887
888     return S_OK;
889 }