dmsynth: Remove DECLSPEC_HIDDEN usage.
[wine.git] / dlls / msdasql / msdasql_main.c
blob2f25498abcabdbee413bb4fbe0406ee64f6eff19
1 /*
2 * Copyright 2019 Alistair Leslie-Hughes
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define COBJMACROS
21 #include <stdarg.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "objbase.h"
26 #include "oledb.h"
27 #include "rpcproxy.h"
28 #include "wine/debug.h"
29 #include "oledberr.h"
31 #include "initguid.h"
32 #include "msdasql.h"
33 #include "odbcinst.h"
34 #include "sqlext.h"
35 #include "sqlucode.h"
37 #include "msdasql_private.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(msdasql);
41 DEFINE_GUID(DBPROPSET_DATASOURCEINFO, 0xc8b522bb, 0x5cf3, 0x11ce, 0xad, 0xe5, 0x00, 0xaa, 0x00, 0x44, 0x77, 0x3d);
42 DEFINE_GUID(DBPROPSET_DBINIT, 0xc8b522bc, 0x5cf3, 0x11ce, 0xad, 0xe5, 0x00, 0xaa, 0x00, 0x44, 0x77, 0x3d);
43 DEFINE_GUID(DBPROPSET_ROWSET, 0xc8b522be, 0x5cf3, 0x11ce, 0xad, 0xe5, 0x00, 0xaa, 0x00, 0x44, 0x77, 0x3d);
45 DEFINE_GUID(DBGUID_DEFAULT, 0xc8b521fb, 0x5cf3, 0x11ce, 0xad, 0xe5, 0x00, 0xaa, 0x00, 0x44, 0x77, 0x3d);
47 void dump_sql_diag_records(SQLSMALLINT type, SQLHANDLE handle)
49 SQLCHAR state[6], msg[SQL_MAX_MESSAGE_LENGTH];
50 SQLINTEGER native;
51 SQLSMALLINT i = 1, len;
53 if (!TRACE_ON(msdasql))
54 return;
56 while(SQLGetDiagRec(type, handle, i, state, &native, msg, sizeof(msg), &len) == SQL_SUCCESS)
58 WARN("%d: %s: %s\n", i, state, msg);
59 i++;
63 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
65 *ppv = NULL;
67 if(IsEqualGUID(&IID_IUnknown, riid)) {
68 TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv);
69 *ppv = iface;
70 }else if(IsEqualGUID(&IID_IClassFactory, riid)) {
71 TRACE("(%p)->(IID_IClassFactory %p)\n", iface, ppv);
72 *ppv = iface;
75 if(*ppv) {
76 IUnknown_AddRef((IUnknown*)*ppv);
77 return S_OK;
80 WARN("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppv);
81 return E_NOINTERFACE;
84 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
86 TRACE("(%p)\n", iface);
87 return 2;
90 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
92 TRACE("(%p)\n", iface);
93 return 1;
96 static HRESULT create_msdasql_provider(REFIID riid, void **ppv);
97 static HRESULT create_msdasql_enumerator(REFIID riid, void **ppv);
99 HRESULT WINAPI msdasql_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv)
101 TRACE("(%p %s %p)\n", outer, debugstr_guid(riid), ppv);
103 return create_msdasql_provider(riid, ppv);
106 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL fLock)
108 TRACE("(%p)->(%x)\n", iface, fLock);
109 return S_OK;
112 static const IClassFactoryVtbl cfmsdasqlVtbl = {
113 ClassFactory_QueryInterface,
114 ClassFactory_AddRef,
115 ClassFactory_Release,
116 msdasql_CreateInstance,
117 ClassFactory_LockServer
120 HRESULT WINAPI enumerationcf_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv)
122 TRACE("(%p %s %p)\n", outer, debugstr_guid(riid), ppv);
124 return create_msdasql_enumerator(riid, ppv);
127 static const IClassFactoryVtbl enumfactoryVtbl =
129 ClassFactory_QueryInterface,
130 ClassFactory_AddRef,
131 ClassFactory_Release,
132 enumerationcf_CreateInstance,
133 ClassFactory_LockServer
136 static IClassFactory cfmsdasql = { &cfmsdasqlVtbl };
137 static IClassFactory enumfactory = { &enumfactoryVtbl };
139 HRESULT WINAPI DllGetClassObject( REFCLSID rclsid, REFIID riid, void **ppv )
141 TRACE("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
143 if (IsEqualGUID(&CLSID_MSDASQL, rclsid))
144 return IClassFactory_QueryInterface(&cfmsdasql, riid, ppv);
145 else if (IsEqualGUID(&CLSID_MSDASQL_ENUMERATOR, rclsid))
146 return IClassFactory_QueryInterface(&enumfactory, riid, ppv);
148 return CLASS_E_CLASSNOTAVAILABLE;
151 struct dbproperty
153 const WCHAR *name;
154 DBPROPID id;
155 DBPROPOPTIONS options;
156 VARTYPE type;
157 HRESULT (*convert_dbproperty)(const WCHAR *src, VARIANT *dest);
160 struct mode_propval
162 const WCHAR *name;
163 DWORD value;
166 static int __cdecl dbmodeprop_compare(const void *a, const void *b)
168 const WCHAR *src = a;
169 const struct mode_propval *propval = b;
170 return wcsicmp(src, propval->name);
173 static HRESULT convert_dbproperty_mode(const WCHAR *src, VARIANT *dest)
175 struct mode_propval mode_propvals[] =
177 { L"Read", DB_MODE_READ },
178 { L"ReadWrite", DB_MODE_READWRITE },
179 { L"Share Deny None", DB_MODE_SHARE_DENY_NONE },
180 { L"Share Deny Read", DB_MODE_SHARE_DENY_READ },
181 { L"Share Deny Write", DB_MODE_SHARE_DENY_WRITE },
182 { L"Share Exclusive", DB_MODE_SHARE_EXCLUSIVE },
183 { L"Write", DB_MODE_WRITE },
185 struct mode_propval *prop;
187 if ((prop = bsearch(src, mode_propvals, ARRAY_SIZE(mode_propvals),
188 sizeof(struct mode_propval), dbmodeprop_compare)))
190 V_VT(dest) = VT_I4;
191 V_I4(dest) = prop->value;
192 TRACE("%s = %#lx\n", debugstr_w(src), prop->value);
193 return S_OK;
196 return E_FAIL;
199 static const struct dbproperty dbproperties[] =
201 { L"Password", DBPROP_AUTH_PASSWORD, DBPROPOPTIONS_OPTIONAL, VT_BSTR },
202 { L"Persist Security Info", DBPROP_AUTH_PERSIST_SENSITIVE_AUTHINFO, DBPROPOPTIONS_OPTIONAL, VT_BOOL },
203 { L"User ID", DBPROP_AUTH_USERID, DBPROPOPTIONS_OPTIONAL, VT_BSTR },
204 { L"Data Source", DBPROP_INIT_DATASOURCE, DBPROPOPTIONS_REQUIRED, VT_BSTR },
205 { L"Window Handle", DBPROP_INIT_HWND, DBPROPOPTIONS_OPTIONAL, sizeof(void *) == 8 ? VT_I8 : VT_I4 },
206 { L"Location", DBPROP_INIT_LOCATION, DBPROPOPTIONS_OPTIONAL, VT_BSTR },
207 { L"Mode", DBPROP_INIT_MODE, DBPROPOPTIONS_OPTIONAL, VT_I4, convert_dbproperty_mode },
208 { L"Prompt", DBPROP_INIT_PROMPT, DBPROPOPTIONS_OPTIONAL, VT_I2 },
209 { L"Connect Timeout", DBPROP_INIT_TIMEOUT, DBPROPOPTIONS_OPTIONAL, VT_I4 },
210 { L"Extended Properties", DBPROP_INIT_PROVIDERSTRING, DBPROPOPTIONS_REQUIRED, VT_BSTR },
211 { L"Locale Identifier", DBPROP_INIT_LCID, DBPROPOPTIONS_OPTIONAL, VT_I4 },
212 { L"Initial Catalog", DBPROP_INIT_CATALOG, DBPROPOPTIONS_OPTIONAL, VT_BSTR },
213 { L"OLE DB Services", DBPROP_INIT_OLEDBSERVICES, DBPROPOPTIONS_OPTIONAL, VT_I4 },
214 { L"General Timeout", DBPROP_INIT_GENERALTIMEOUT, DBPROPOPTIONS_OPTIONAL, VT_I4 },
217 struct msdasql_prop
219 VARTYPE id;
220 VARIANT value;
223 struct msdasql
225 IUnknown MSDASQL_iface;
226 IDBProperties IDBProperties_iface;
227 IDBInitialize IDBInitialize_iface;
228 IDBCreateSession IDBCreateSession_iface;
229 IPersist IPersist_iface;
231 LONG ref;
232 struct msdasql_prop properties[14];
234 /* ODBC Support */
235 HENV henv;
236 HDBC hdbc;
239 static inline struct msdasql *impl_from_IUnknown(IUnknown *iface)
241 return CONTAINING_RECORD(iface, struct msdasql, MSDASQL_iface);
244 static inline struct msdasql *impl_from_IDBProperties(IDBProperties *iface)
246 return CONTAINING_RECORD(iface, struct msdasql, IDBProperties_iface);
249 static inline struct msdasql *impl_from_IDBInitialize(IDBInitialize *iface)
251 return CONTAINING_RECORD(iface, struct msdasql, IDBInitialize_iface);
254 static inline struct msdasql *impl_from_IDBCreateSession(IDBCreateSession *iface)
256 return CONTAINING_RECORD(iface, struct msdasql, IDBCreateSession_iface);
259 static inline struct msdasql *impl_from_IPersist( IPersist *iface )
261 return CONTAINING_RECORD( iface, struct msdasql, IPersist_iface );
264 static HRESULT WINAPI msdsql_QueryInterface(IUnknown *iface, REFIID riid, void **out)
266 struct msdasql *provider = impl_from_IUnknown(iface);
268 TRACE("(%p)->(%s %p)\n", provider, debugstr_guid(riid), out);
270 if(IsEqualGUID(riid, &IID_IUnknown) ||
271 IsEqualGUID(riid, &CLSID_MSDASQL))
273 *out = &provider->MSDASQL_iface;
275 else if(IsEqualGUID(riid, &IID_IDBProperties))
277 *out = &provider->IDBProperties_iface;
279 else if ( IsEqualGUID(riid, &IID_IDBInitialize))
281 *out = &provider->IDBInitialize_iface;
283 else if (IsEqualGUID(riid, &IID_IDBCreateSession))
285 *out = &provider->IDBCreateSession_iface;
287 else if(IsEqualGUID(&IID_IPersist, riid))
289 *out = &provider->IPersist_iface;
291 else
293 FIXME("(%s, %p)\n", debugstr_guid(riid), out);
294 *out = NULL;
295 return E_NOINTERFACE;
298 IUnknown_AddRef((IUnknown*)*out);
299 return S_OK;
302 static ULONG WINAPI msdsql_AddRef(IUnknown *iface)
304 struct msdasql *provider = impl_from_IUnknown(iface);
305 ULONG ref = InterlockedIncrement(&provider->ref);
307 TRACE("(%p) ref=%lu\n", provider, ref);
309 return ref;
312 static ULONG WINAPI msdsql_Release(IUnknown *iface)
314 struct msdasql *provider = impl_from_IUnknown(iface);
315 ULONG ref = InterlockedDecrement(&provider->ref);
317 TRACE("(%p) ref=%lu\n", provider, ref);
319 if (!ref)
321 SQLDisconnect(provider->hdbc);
323 SQLFreeHandle(SQL_HANDLE_DBC, provider->hdbc);
324 SQLFreeHandle(SQL_HANDLE_ENV, provider->henv);
325 free(provider);
328 return ref;
331 static const IUnknownVtbl msdsql_vtbl =
333 msdsql_QueryInterface,
334 msdsql_AddRef,
335 msdsql_Release
338 static HRESULT WINAPI dbprops_QueryInterface(IDBProperties *iface, REFIID riid, void **ppvObject)
340 struct msdasql *provider = impl_from_IDBProperties(iface);
342 return IUnknown_QueryInterface(&provider->MSDASQL_iface, riid, ppvObject);
345 static ULONG WINAPI dbprops_AddRef(IDBProperties *iface)
347 struct msdasql *provider = impl_from_IDBProperties(iface);
349 return IUnknown_AddRef(&provider->MSDASQL_iface);
352 static ULONG WINAPI dbprops_Release(IDBProperties *iface)
354 struct msdasql *provider = impl_from_IDBProperties(iface);
356 return IUnknown_Release(&provider->MSDASQL_iface);
359 static HRESULT WINAPI dbprops_GetProperties(IDBProperties *iface, ULONG cPropertyIDSets,
360 const DBPROPIDSET rgPropertyIDSets[], ULONG *pcPropertySets, DBPROPSET **prgPropertySets)
362 struct msdasql *provider = impl_from_IDBProperties(iface);
363 int i, j, k;
364 DBPROPSET *propset;
366 TRACE("(%p)->(%ld %p %p %p)\n", provider, cPropertyIDSets, rgPropertyIDSets, pcPropertySets, prgPropertySets);
368 *pcPropertySets = 1;
370 if (cPropertyIDSets != 1)
372 FIXME("Currently only 1 property set supported.\n");
373 cPropertyIDSets = 1;
376 propset = CoTaskMemAlloc(cPropertyIDSets * sizeof(DBPROPSET));
378 if (IsEqualGUID(&rgPropertyIDSets[0].guidPropertySet, &DBPROPSET_DATASOURCEINFO))
380 TRACE("Propertyset DBPROPSET_DATASOURCEINFO not supported\n");
381 propset->guidPropertySet = rgPropertyIDSets[0].guidPropertySet;
382 propset->cProperties = rgPropertyIDSets[0].cPropertyIDs;
384 propset->rgProperties = CoTaskMemAlloc(propset->cProperties * sizeof(DBPROP));
386 for (j=0; j < propset->cProperties; j++)
388 propset->rgProperties[j].dwPropertyID = rgPropertyIDSets[0].rgPropertyIDs[j];
389 propset->rgProperties[j].dwStatus = DBPROPSTATUS_NOTSUPPORTED;
392 *prgPropertySets = propset;
394 return DB_E_ERRORSOCCURRED;
397 propset->guidPropertySet = DBPROPSET_DBINIT;
399 for (i=0; i < cPropertyIDSets; i++)
401 TRACE("Property id %d (count %ld, set %s)\n", i, rgPropertyIDSets[i].cPropertyIDs,
402 debugstr_guid(&rgPropertyIDSets[i].guidPropertySet));
404 propset->cProperties = rgPropertyIDSets[i].cPropertyIDs;
405 propset->rgProperties = CoTaskMemAlloc(propset->cProperties * sizeof(DBPROP));
407 for (j=0; j < propset->cProperties; j++)
409 propset->rgProperties[j].dwPropertyID = rgPropertyIDSets[i].rgPropertyIDs[j];
411 for(k = 0; k < ARRAY_SIZE(provider->properties); k++)
413 if (provider->properties[k].id == rgPropertyIDSets[i].rgPropertyIDs[j])
415 V_VT(&propset->rgProperties[j].vValue) = VT_EMPTY;
416 VariantCopy(&propset->rgProperties[j].vValue, &provider->properties[k].value);
417 break;
423 *prgPropertySets = propset;
425 return S_OK;
428 static HRESULT WINAPI dbprops_GetPropertyInfo(IDBProperties *iface, ULONG cPropertyIDSets,
429 const DBPROPIDSET rgPropertyIDSets[], ULONG *pcPropertyInfoSets,
430 DBPROPINFOSET **prgPropertyInfoSets, OLECHAR **ppDescBuffer)
432 struct msdasql *provider = impl_from_IDBProperties(iface);
433 int i;
434 DBPROPINFOSET *infoset;
435 int size = 1;
436 OLECHAR *ptr;
438 TRACE("(%p)->(%ld %p %p %p %p)\n", provider, cPropertyIDSets, rgPropertyIDSets, pcPropertyInfoSets,
439 prgPropertyInfoSets, ppDescBuffer);
441 infoset = CoTaskMemAlloc(sizeof(DBPROPINFOSET));
442 memcpy(&infoset->guidPropertySet, &DBPROPSET_DBINIT, sizeof(GUID));
443 infoset->cPropertyInfos = ARRAY_SIZE(dbproperties);
444 infoset->rgPropertyInfos = CoTaskMemAlloc(sizeof(DBPROPINFO) * ARRAY_SIZE(dbproperties));
446 for(i=0; i < ARRAY_SIZE(dbproperties); i++)
448 size += lstrlenW(dbproperties[i].name) + 1;
451 ptr = *ppDescBuffer = CoTaskMemAlloc(size * sizeof(WCHAR));
452 memset(*ppDescBuffer, 0, size * sizeof(WCHAR));
454 for(i=0; i < ARRAY_SIZE(dbproperties); i++)
456 lstrcpyW(ptr, dbproperties[i].name);
457 infoset->rgPropertyInfos[i].pwszDescription = ptr;
458 infoset->rgPropertyInfos[i].dwPropertyID = dbproperties[i].id;
459 infoset->rgPropertyInfos[i].dwFlags = DBPROPFLAGS_DBINIT | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE;
460 infoset->rgPropertyInfos[i].vtType = dbproperties[i].type;
461 V_VT(&infoset->rgPropertyInfos[i].vValues) = VT_EMPTY;
463 ptr += lstrlenW(dbproperties[i].name) + 1;
466 *pcPropertyInfoSets = 1;
467 *prgPropertyInfoSets = infoset;
469 return S_OK;
472 static HRESULT WINAPI dbprops_SetProperties(IDBProperties *iface, ULONG cPropertySets,
473 DBPROPSET rgPropertySets[])
475 struct msdasql *provider = impl_from_IDBProperties(iface);
476 int i, j, k;
478 TRACE("(%p)->(%ld %p)\n", provider, cPropertySets, rgPropertySets);
480 for (i=0; i < cPropertySets; i++)
482 for (j=0; j < rgPropertySets[i].cProperties; j++)
484 for(k=0; k < ARRAY_SIZE(provider->properties); k++)
486 if (provider->properties[k].id == rgPropertySets[i].rgProperties[j].dwPropertyID)
488 TRACE("Found property %d\n", provider->properties[k].id);
489 VariantCopy(&provider->properties[k].value, &rgPropertySets[i].rgProperties[j].vValue);
490 break;
496 return S_OK;
499 static const struct IDBPropertiesVtbl dbprops_vtbl =
501 dbprops_QueryInterface,
502 dbprops_AddRef,
503 dbprops_Release,
504 dbprops_GetProperties,
505 dbprops_GetPropertyInfo,
506 dbprops_SetProperties
509 static HRESULT WINAPI dbinit_QueryInterface(IDBInitialize *iface, REFIID riid, void **ppvObject)
511 struct msdasql *provider = impl_from_IDBInitialize(iface);
513 return IUnknown_QueryInterface(&provider->MSDASQL_iface, riid, ppvObject);
516 static ULONG WINAPI dbinit_AddRef(IDBInitialize *iface)
518 struct msdasql *provider = impl_from_IDBInitialize(iface);
520 return IUnknown_AddRef(&provider->MSDASQL_iface);
523 static ULONG WINAPI dbinit_Release(IDBInitialize *iface)
525 struct msdasql *provider = impl_from_IDBInitialize(iface);
527 return IUnknown_Release(&provider->MSDASQL_iface);
530 static HRESULT WINAPI dbinit_Initialize(IDBInitialize *iface)
532 struct msdasql *provider = impl_from_IDBInitialize(iface);
533 int i, len;
534 SQLRETURN ret;
535 WCHAR connection[1024], *p = connection, outstr[1024];
537 FIXME("%p semi-stub\n", provider);
539 *p = 0;
540 for(i=0; i < ARRAY_SIZE(provider->properties); i++)
542 if (provider->properties[i].id == DBPROP_INIT_DATASOURCE)
544 len = swprintf(p, ARRAY_SIZE(connection) - (p - connection),
545 L"DSN=%s;", V_BSTR(&provider->properties[i].value));
546 p+= len;
548 else if (provider->properties[i].id == DBPROP_INIT_PROVIDERSTRING)
550 if (V_VT(&provider->properties[i].value) == VT_BSTR && SysStringLen(V_BSTR(&provider->properties[i].value)) )
552 len = swprintf(p, ARRAY_SIZE(connection) - (p - connection),
553 L"%s;", V_BSTR(&provider->properties[i].value));
554 p+= len;
559 ret = SQLDriverConnectW( provider->hdbc, NULL, connection, wcslen(connection),
560 outstr, ARRAY_SIZE(outstr), NULL, 0);
561 TRACE("SQLDriverConnectW ret %d\n", ret);
562 if (ret != SQL_SUCCESS)
564 dump_sql_diag_records(SQL_HANDLE_DBC, provider->hdbc);
566 if (ret != SQL_SUCCESS_WITH_INFO)
567 return E_FAIL;
570 return S_OK;
573 static HRESULT WINAPI dbinit_Uninitialize(IDBInitialize *iface)
575 struct msdasql *provider = impl_from_IDBInitialize(iface);
577 FIXME("%p stub\n", provider);
579 return S_OK;
583 static const struct IDBInitializeVtbl dbinit_vtbl =
585 dbinit_QueryInterface,
586 dbinit_AddRef,
587 dbinit_Release,
588 dbinit_Initialize,
589 dbinit_Uninitialize
592 static HRESULT WINAPI dbsess_QueryInterface(IDBCreateSession *iface, REFIID riid, void **ppvObject)
594 struct msdasql *provider = impl_from_IDBCreateSession(iface);
596 return IUnknown_QueryInterface(&provider->MSDASQL_iface, riid, ppvObject);
599 static ULONG WINAPI dbsess_AddRef(IDBCreateSession *iface)
601 struct msdasql *provider = impl_from_IDBCreateSession(iface);
603 return IUnknown_AddRef(&provider->MSDASQL_iface);
606 static ULONG WINAPI dbsess_Release(IDBCreateSession *iface)
608 struct msdasql *provider = impl_from_IDBCreateSession(iface);
610 return IUnknown_Release(&provider->MSDASQL_iface);
613 static HRESULT WINAPI dbsess_CreateSession(IDBCreateSession *iface, IUnknown *outer, REFIID riid,
614 IUnknown **session)
616 struct msdasql *provider = impl_from_IDBCreateSession(iface);
617 HRESULT hr;
619 TRACE("%p, outer %p, riid %s, session %p stub\n", provider, outer, debugstr_guid(riid), session);
621 if (outer)
622 FIXME("outer currently not supported.\n");
624 hr = create_db_session(riid, &provider->MSDASQL_iface, provider->hdbc, (void**)session);
626 return hr;
629 static const struct IDBCreateSessionVtbl dbsess_vtbl =
631 dbsess_QueryInterface,
632 dbsess_AddRef,
633 dbsess_Release,
634 dbsess_CreateSession
637 static HRESULT WINAPI persist_QueryInterface(IPersist *iface, REFIID riid, void **ppv)
639 struct msdasql *provider = impl_from_IPersist( iface );
640 return IUnknown_QueryInterface(&provider->MSDASQL_iface, riid, ppv);
643 static ULONG WINAPI persist_AddRef(IPersist *iface)
645 struct msdasql *provider = impl_from_IPersist( iface );
646 return IUnknown_AddRef(&provider->MSDASQL_iface);
649 static ULONG WINAPI persist_Release(IPersist *iface)
651 struct msdasql *provider = impl_from_IPersist( iface );
652 return IUnknown_Release(&provider->MSDASQL_iface);
655 static HRESULT WINAPI persist_GetClassID(IPersist *iface, CLSID *classid)
657 struct msdasql *provider = impl_from_IPersist( iface );
659 TRACE("(%p)->(%p)\n", provider, classid);
661 if(!classid)
662 return E_INVALIDARG;
664 *classid = CLSID_MSDASQL;
665 return S_OK;
669 static const IPersistVtbl persistVtbl = {
670 persist_QueryInterface,
671 persist_AddRef,
672 persist_Release,
673 persist_GetClassID
676 static HRESULT create_msdasql_provider(REFIID riid, void **ppv)
678 struct msdasql *provider;
679 HRESULT hr;
680 int i;
682 provider = malloc(sizeof(struct msdasql));
683 if (!provider)
684 return E_OUTOFMEMORY;
686 provider->MSDASQL_iface.lpVtbl = &msdsql_vtbl;
687 provider->IDBProperties_iface.lpVtbl = &dbprops_vtbl;
688 provider->IDBInitialize_iface.lpVtbl = &dbinit_vtbl;
689 provider->IDBCreateSession_iface.lpVtbl = &dbsess_vtbl;
690 provider->IPersist_iface.lpVtbl = &persistVtbl;
691 provider->ref = 1;
693 for(i=0; i < ARRAY_SIZE(dbproperties); i++)
695 provider->properties[i].id = dbproperties[i].id;
696 VariantInit(&provider->properties[i].value);
698 /* Only the follow are initialized to a value */
699 switch(dbproperties[i].id)
701 case DBPROP_INIT_PROMPT:
702 V_VT(&provider->properties[i].value) = dbproperties[i].type;
703 V_I2(&provider->properties[i].value) = 4;
704 break;
705 case DBPROP_INIT_LCID:
706 V_VT(&provider->properties[i].value) = dbproperties[i].type;
707 V_I4(&provider->properties[i].value) = GetUserDefaultLCID();
708 break;
709 case DBPROP_INIT_OLEDBSERVICES:
710 V_VT(&provider->properties[i].value) = dbproperties[i].type;
711 V_I4(&provider->properties[i].value) = -1;
712 break;
713 default:
714 V_VT(&provider->properties[i].value) = VT_EMPTY;
718 SQLAllocHandle(SQL_HANDLE_ENV, NULL, &provider->henv );
719 if (SQLSetEnvAttr(provider->henv, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3_80, 0) == SQL_ERROR)
721 WARN("Falling back to SQL_OV_ODBC3\n");
722 SQLSetEnvAttr(provider->henv, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3, 0);
725 SQLAllocHandle(SQL_HANDLE_DBC, provider->henv, &provider->hdbc);
727 hr = IUnknown_QueryInterface(&provider->MSDASQL_iface, riid, ppv);
728 IUnknown_Release(&provider->MSDASQL_iface);
729 return hr;
732 struct msdasql_enum
734 ISourcesRowset ISourcesRowset_iface;
735 LONG ref;
738 static inline struct msdasql_enum *msdasql_enum_from_ISourcesRowset(ISourcesRowset *iface)
740 return CONTAINING_RECORD(iface, struct msdasql_enum, ISourcesRowset_iface);
743 static HRESULT WINAPI msdasql_enum_QueryInterface(ISourcesRowset *iface, REFIID riid, void **out)
745 struct msdasql_enum *enumerator = msdasql_enum_from_ISourcesRowset(iface);
747 TRACE("(%p)->(%s %p)\n", enumerator, debugstr_guid(riid), out);
749 if(IsEqualGUID(riid, &IID_IUnknown) ||
750 IsEqualGUID(riid, &IID_ISourcesRowset ) )
752 *out = &enumerator->ISourcesRowset_iface;
754 else
756 FIXME("(%s, %p)\n", debugstr_guid(riid), out);
757 *out = NULL;
758 return E_NOINTERFACE;
761 IUnknown_AddRef((IUnknown*)*out);
762 return S_OK;
765 static ULONG WINAPI msdasql_enum_AddRef(ISourcesRowset *iface)
767 struct msdasql_enum *enumerator = msdasql_enum_from_ISourcesRowset(iface);
768 ULONG ref = InterlockedIncrement(&enumerator->ref);
770 TRACE("(%p) ref=%lu\n", enumerator, ref);
772 return ref;
775 static ULONG WINAPI msdasql_enum_Release(ISourcesRowset *iface)
777 struct msdasql_enum *enumerator = msdasql_enum_from_ISourcesRowset(iface);
778 ULONG ref = InterlockedDecrement(&enumerator->ref);
780 TRACE("(%p) ref=%lu\n", enumerator, ref);
782 if (!ref)
784 free(enumerator);
787 return ref;
790 struct msdasql_enum_rowset
792 IRowset IRowset_iface;
793 IAccessor IAccessor_iface;
794 LONG ref;
797 static inline struct msdasql_enum_rowset *msdasql_rs_from_IRowset(IRowset *iface)
799 return CONTAINING_RECORD(iface, struct msdasql_enum_rowset, IRowset_iface);
802 static inline struct msdasql_enum_rowset *msdasql_enum_from_IAccessor ( IAccessor *iface )
804 return CONTAINING_RECORD( iface, struct msdasql_enum_rowset, IAccessor_iface );
807 static HRESULT WINAPI enum_rowset_QueryInterface(IRowset *iface, REFIID riid, void **ppv)
809 struct msdasql_enum_rowset *rowset = msdasql_rs_from_IRowset( iface );
811 TRACE( "%p, %s, %p\n", rowset, debugstr_guid(riid), ppv );
812 *ppv = NULL;
814 if(IsEqualGUID(&IID_IUnknown, riid) ||
815 IsEqualGUID(&IID_IRowset, riid))
817 *ppv = &rowset->IRowset_iface;
819 else if(IsEqualGUID(&IID_IAccessor, riid))
821 *ppv = &rowset->IAccessor_iface;
824 if(*ppv)
826 IUnknown_AddRef((IUnknown*)*ppv);
827 return S_OK;
830 FIXME("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppv);
831 return E_NOINTERFACE;
834 static ULONG WINAPI enum_rowset_AddRef(IRowset *iface)
836 struct msdasql_enum_rowset *rowset = msdasql_rs_from_IRowset( iface );
837 LONG refs = InterlockedIncrement( &rowset->ref );
838 TRACE( "%p new refcount %ld\n", rowset, refs );
839 return refs;
842 static ULONG WINAPI enum_rowset_Release(IRowset *iface)
844 struct msdasql_enum_rowset *rowset = msdasql_rs_from_IRowset( iface );
845 LONG refs = InterlockedDecrement( &rowset->ref );
846 TRACE( "%p new refcount %ld\n", rowset, refs );
847 if (!refs)
849 TRACE( "destroying %p\n", rowset );
850 free( rowset );
852 return refs;
855 static HRESULT WINAPI enum_rowset_AddRefRows(IRowset *iface, DBCOUNTITEM count,
856 const HROW rows[], DBREFCOUNT ref_counts[], DBROWSTATUS status[])
858 struct msdasql_enum_rowset *rowset = msdasql_rs_from_IRowset( iface );
860 FIXME("%p, %Iu, %p, %p, %p\n", rowset, count, rows, ref_counts, status);
862 return E_NOTIMPL;
865 static HRESULT WINAPI enum_rowset_GetData(IRowset *iface, HROW row, HACCESSOR accessor, void *data)
867 struct msdasql_enum_rowset *rowset = msdasql_rs_from_IRowset( iface );
869 FIXME("%p, %Iu, %Iu, %p\n", rowset, row, accessor, data);
871 return E_NOTIMPL;
874 static HRESULT WINAPI enum_rowset_GetNextRows(IRowset *iface, HCHAPTER reserved, DBROWOFFSET offset,
875 DBROWCOUNT count, DBCOUNTITEM *obtained, HROW **rows)
877 struct msdasql_enum_rowset *rowset = msdasql_rs_from_IRowset( iface );
879 FIXME("%p, %Iu, %Iu, %Iu, %p, %p\n", rowset, reserved, offset, count, obtained, rows);
881 if (!obtained || !rows)
882 return E_INVALIDARG;
884 *obtained = 0;
886 if (!count)
887 return S_OK;
889 return DB_S_ENDOFROWSET;
892 static HRESULT WINAPI enum_rowset_ReleaseRows(IRowset *iface, DBCOUNTITEM count,
893 const HROW rows[], DBROWOPTIONS options[], DBREFCOUNT ref_counts[], DBROWSTATUS status[])
895 struct msdasql_enum_rowset *rowset = msdasql_rs_from_IRowset( iface );
897 FIXME("%p, %Iu, %p, %p, %p, %p\n", rowset, count, rows, options, ref_counts, status);
899 return S_OK;
902 static HRESULT WINAPI enum_rowset_RestartPosition(IRowset *iface, HCHAPTER reserved)
904 struct msdasql_enum_rowset *rowset = msdasql_rs_from_IRowset( iface );
906 FIXME("%p, %Iu\n", rowset, reserved);
908 return S_OK;
911 static const struct IRowsetVtbl enum_rowset_vtbl =
913 enum_rowset_QueryInterface,
914 enum_rowset_AddRef,
915 enum_rowset_Release,
916 enum_rowset_AddRefRows,
917 enum_rowset_GetData,
918 enum_rowset_GetNextRows,
919 enum_rowset_ReleaseRows,
920 enum_rowset_RestartPosition
923 static HRESULT WINAPI enum_rs_accessor_QueryInterface(IAccessor *iface, REFIID riid, void **out)
925 struct msdasql_enum_rowset *rowset = msdasql_enum_from_IAccessor( iface );
926 return IRowset_QueryInterface(&rowset->IRowset_iface, riid, out);
929 static ULONG WINAPI enum_rs_accessor_AddRef(IAccessor *iface)
931 struct msdasql_enum_rowset *rowset = msdasql_enum_from_IAccessor( iface );
932 return IRowset_AddRef(&rowset->IRowset_iface);
935 static ULONG WINAPI enum_rs_accessor_Release(IAccessor *iface)
937 struct msdasql_enum_rowset *rowset = msdasql_enum_from_IAccessor( iface );
938 return IRowset_Release(&rowset->IRowset_iface);
941 static HRESULT WINAPI enum_rs_accessor_AddRefAccessor(IAccessor *iface, HACCESSOR accessor, DBREFCOUNT *count)
943 struct msdasql_enum_rowset *rowset = msdasql_enum_from_IAccessor( iface );
944 FIXME("%p, %Iu, %p\n", rowset, accessor, count);
945 return E_NOTIMPL;
948 static HRESULT WINAPI enum_rs_accessor_CreateAccessor(IAccessor *iface, DBACCESSORFLAGS flags,
949 DBCOUNTITEM count, const DBBINDING bindings[], DBLENGTH row_size, HACCESSOR *accessor,
950 DBBINDSTATUS status[])
952 struct msdasql_enum_rowset *rowset = msdasql_enum_from_IAccessor( iface );
954 FIXME("%p 0x%08lx, %Iu, %p, %Iu, %p, %p\n", rowset, flags, count, bindings, row_size, accessor, status);
956 if (accessor)
957 *accessor = 0xdeadbeef;
959 return S_OK;
962 static HRESULT WINAPI enum_rs_accessor_GetBindings(IAccessor *iface, HACCESSOR accessor,
963 DBACCESSORFLAGS *flags, DBCOUNTITEM *count, DBBINDING **bindings)
965 struct msdasql_enum_rowset *rowset = msdasql_enum_from_IAccessor( iface );
966 FIXME("%p, %Iu, %p, %p, %p\n", rowset, accessor, flags, count, bindings);
967 return E_NOTIMPL;
970 static HRESULT WINAPI enum_rs_accessor_ReleaseAccessor(IAccessor *iface, HACCESSOR accessor, DBREFCOUNT *count)
972 struct msdasql_enum_rowset *rowset = msdasql_enum_from_IAccessor( iface );
974 FIXME("%p, %Iu, %p\n", rowset, accessor, count);
976 if (count)
977 *count = 0;
979 return S_OK;
982 struct IAccessorVtbl enum_accessor_vtbl =
984 enum_rs_accessor_QueryInterface,
985 enum_rs_accessor_AddRef,
986 enum_rs_accessor_Release,
987 enum_rs_accessor_AddRefAccessor,
988 enum_rs_accessor_CreateAccessor,
989 enum_rs_accessor_GetBindings,
990 enum_rs_accessor_ReleaseAccessor
993 static HRESULT WINAPI msdasql_enum_GetSourcesRowset(ISourcesRowset *iface, IUnknown *outer, REFIID riid, ULONG sets,
994 DBPROPSET properties[], IUnknown **rowset)
996 struct msdasql_enum *enumerator = msdasql_enum_from_ISourcesRowset(iface);
997 struct msdasql_enum_rowset *enum_rs;
998 HRESULT hr;
1000 TRACE("(%p) %p, %s, %lu, %p, %p\n", enumerator, outer, debugstr_guid(riid), sets, properties, rowset);
1002 enum_rs = malloc(sizeof(*enum_rs));
1003 enum_rs->IRowset_iface.lpVtbl = &enum_rowset_vtbl;
1004 enum_rs->IAccessor_iface.lpVtbl = &enum_accessor_vtbl;
1005 enum_rs->ref = 1;
1007 hr = IRowset_QueryInterface(&enum_rs->IRowset_iface, riid, (void**)rowset);
1008 IRowset_Release(&enum_rs->IRowset_iface);
1009 return hr;
1012 static const ISourcesRowsetVtbl msdsqlenum_vtbl =
1014 msdasql_enum_QueryInterface,
1015 msdasql_enum_AddRef,
1016 msdasql_enum_Release,
1017 msdasql_enum_GetSourcesRowset
1020 static HRESULT create_msdasql_enumerator(REFIID riid, void **ppv)
1022 struct msdasql_enum *enumerator;
1023 HRESULT hr;
1025 enumerator = malloc(sizeof(*enumerator));
1026 if (!enumerator)
1027 return E_OUTOFMEMORY;
1029 enumerator->ISourcesRowset_iface.lpVtbl = &msdsqlenum_vtbl;
1030 enumerator->ref = 1;
1032 hr = IUnknown_QueryInterface(&enumerator->ISourcesRowset_iface, riid, ppv);
1033 IUnknown_Release(&enumerator->ISourcesRowset_iface);
1034 return hr;