oledb32: Partial implementation of GetDataSource()
Nikolay Sivov
nsivov at codeweavers.com
Mon Dec 24 06:25:30 CST 2012
http://bugs.winehq.org/show_bug.cgi?id=32364
-------------- next part --------------
>From 7171ecb475c54a1db7033895cbb317feba6f485e Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <nsivov at codeweavers.com>
Date: Sun, 23 Dec 2012 02:09:50 +0400
Subject: [PATCH 1/3] Partial implementation of GetDataSource()
---
dlls/oledb32/datainit.c | 130 +++++++++++++++++++++++++++++++++--------
dlls/oledb32/tests/database.c | 30 ++++++++++
include/oledberr.h | 2 +
3 files changed, 139 insertions(+), 23 deletions(-)
diff --git a/dlls/oledb32/datainit.c b/dlls/oledb32/datainit.c
index 78a005d..f940e4d 100644
--- a/dlls/oledb32/datainit.c
+++ b/dlls/oledb32/datainit.c
@@ -273,21 +273,121 @@ static ULONG WINAPI datainit_Release(IDataInitialize *iface)
return ref;
}
+static void free_dbpropset(ULONG count, DBPROPSET *propset)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ {
+ int p;
+
+ for (p = 0; p < propset[i].cProperties; p++)
+ VariantClear(&propset[i].rgProperties[p].vValue);
+
+ CoTaskMemFree(propset[i].rgProperties);
+ }
+ CoTaskMemFree(propset);
+}
+
/*** IDataInitialize methods ***/
-static HRESULT WINAPI datainit_GetDataSource(IDataInitialize *iface, IUnknown *pUnkOuter, DWORD dwClsCtx,
- LPWSTR pwszInitializationString, REFIID riid, IUnknown **ppDataSource)
+static HRESULT WINAPI datainit_GetDataSource(IDataInitialize *iface, IUnknown *outer, DWORD clsctx,
+ LPWSTR initstring, REFIID riid, IUnknown **datasource)
{
+ static const WCHAR providerW[] = {'P','r','o','v','i','d','e','r','=',0};
+ static const WCHAR msdasqlW[] = {'M','S','D','A','S','Q','L',0};
datainit *This = impl_from_IDataInitialize(iface);
+ CLSID provclsid;
+ WCHAR *prov;
+ HRESULT hr;
- FIXME("(%p)->(%p %d %s %s %p)\n", This, pUnkOuter, dwClsCtx, debugstr_w(pwszInitializationString),
- debugstr_guid(riid), ppDataSource);
+ FIXME("(%p)->(%p 0x%x %s %s %p): semi-stub\n", This, outer, clsctx, debugstr_w(initstring), debugstr_guid(riid), datasource);
- if(IsEqualIID(riid, &IID_IDBInitialize))
+ /* first get provider name */
+ provclsid = IID_NULL;
+ if (initstring && (prov = strstrW(initstring, providerW)))
{
- return create_db_init( (LPVOID*)ppDataSource);
+ WCHAR *start, *progid;
+ int len;
+
+ prov += sizeof(providerW)/sizeof(WCHAR)-1;
+ start = prov;
+ while (*prov && *prov != ';')
+ ++prov;
+ TRACE("got provider %s\n", debugstr_wn(start, prov-start));
+
+ len = (prov - start)*sizeof(WCHAR);
+ progid = CoTaskMemAlloc(len + sizeof(WCHAR));
+ if (!progid) return E_OUTOFMEMORY;
+
+ memcpy(progid, start, len);
+ progid[len] = 0;
+
+ hr = CLSIDFromProgID(progid, &provclsid);
+ CoTaskMemFree(progid);
+ if (FAILED(hr))
+ {
+ ERR("provider %s not registered\n", debugstr_wn(start, prov-start));
+ return hr;
+ }
+ }
+ else
+ {
+ hr = CLSIDFromProgID(msdasqlW, &provclsid);
+ if (FAILED(hr))
+ ERR("ODBC provider for OLE DB not registered\n");
}
- return E_NOTIMPL;
+ /* check for provider mismatch if it was specified in init string */
+ if (*datasource && prov)
+ {
+ IDBProperties *dbprops;
+ DBPROPIDSET propidset;
+ DBPROPSET *propset;
+ enum DBPROPENUM prop;
+ CLSID initprov;
+ ULONG count;
+
+ hr = IUnknown_QueryInterface(*datasource, &IID_IDBProperties, (void**)&dbprops);
+ if (FAILED(hr))
+ {
+ WARN("provider doesn't support IDBProperties\n");
+ return hr;
+ }
+
+ prop = DBPROP_INIT_DATASOURCE;
+ propidset.rgPropertyIDs = ∝
+ propidset.cPropertyIDs = 1;
+ propidset.guidPropertySet = DBPROPSET_DBINIT;
+ count = 0;
+ propset = NULL;
+ hr = IDBProperties_GetProperties(dbprops, 1, &propidset, &count, &propset);
+ IDBProperties_Release(dbprops);
+ if (FAILED(hr))
+ {
+ WARN("GetProperties failed for datasource, 0x%08x\n", hr);
+ return hr;
+ }
+
+ TRACE("initial data source provider %s\n", debugstr_w(V_BSTR(&propset->rgProperties[0].vValue)));
+ initprov = IID_NULL;
+ CLSIDFromProgID(V_BSTR(&propset->rgProperties[0].vValue), &initprov);
+ free_dbpropset(count, propset);
+
+ if (!IsEqualIID(&provclsid, &initprov)) return DB_E_MISMATCHEDPROVIDER;
+ }
+
+ if (!*datasource)
+ {
+ if (!IsEqualIID(&provclsid, &IID_NULL))
+ hr = CoCreateInstance(&provclsid, outer, clsctx, riid, (void**)datasource);
+
+ if (FAILED(hr) && IsEqualIID(riid, &IID_IDBInitialize))
+ hr = create_db_init((void**)datasource);
+ }
+
+ /* FIXME: set properties from init string */
+
+ return hr;
}
/* returns character length of string representation */
@@ -342,22 +442,6 @@ static WCHAR *get_propinfo_descr(DBPROP *prop, DBPROPINFOSET *propinfoset)
return NULL;
}
-static void free_dbpropset(ULONG count, DBPROPSET *propset)
-{
- int i;
-
- for (i = 0; i < count; i++)
- {
- int p;
-
- for (p = 0; p < propset[i].cProperties; p++)
- VariantClear(&propset[i].rgProperties[p].vValue);
-
- CoTaskMemFree(propset[i].rgProperties);
- }
- CoTaskMemFree(propset);
-}
-
static void free_dbpropinfoset(ULONG count, DBPROPINFOSET *propinfoset)
{
int i;
diff --git a/dlls/oledb32/tests/database.c b/dlls/oledb32/tests/database.c
index f093d17..a5936c4 100644
--- a/dlls/oledb32/tests/database.c
+++ b/dlls/oledb32/tests/database.c
@@ -33,6 +33,10 @@
static void test_database(void)
{
+ static WCHAR initstring[] = {'P','r','o','v','i','d','e','r','=','M','i','c','r','o','s','o','f','t','.',
+ 'J','e','t','.','O','L','E','D','B','.','4','.','0',';',
+ 'D','a','t','a',' ','S','o','u','r','c','e','=','d','u','m','m','y',';',0};
+ static WCHAR initstring2[] = {'D','a','t','a',' ','S','o','u','r','c','e','=','d','u','m','m','y',';',0};
HRESULT hr;
IDBInitialize *dbinit = NULL;
IDataInitialize *datainit = NULL;
@@ -60,6 +64,32 @@ static void test_database(void)
IDBInitialize_Release(dbinit);
}
+ hr = IDataInitialize_GetDataSource(datainit, NULL, CLSCTX_INPROC_SERVER, initstring, &IID_IDBInitialize, (IUnknown **)&dbinit);
+ if (hr == S_OK)
+ {
+ IDBProperties *props = NULL;
+
+ hr = IDBInitialize_QueryInterface(dbinit, &IID_IDBProperties, (void**)&props);
+ ok(hr == S_OK, "got %08x\n", hr);
+ if(SUCCEEDED(hr))
+ IDBProperties_Release(props);
+
+ IDBInitialize_Release(dbinit);
+ }
+
+ hr = IDataInitialize_GetDataSource(datainit, NULL, CLSCTX_INPROC_SERVER, initstring2, &IID_IDBInitialize, (IUnknown **)&dbinit);
+ if (hr == S_OK)
+ {
+ IDBProperties *props = NULL;
+
+ hr = IDBInitialize_QueryInterface(dbinit, &IID_IDBProperties, (void**)&props);
+ ok(hr == S_OK, "got %08x\n", hr);
+ if(SUCCEEDED(hr))
+ IDBProperties_Release(props);
+
+ IDBInitialize_Release(dbinit);
+ }
+
IDataInitialize_Release(datainit);
}
diff --git a/include/oledberr.h b/include/oledberr.h
index 94db602..c2033b6 100644
--- a/include/oledberr.h
+++ b/include/oledberr.h
@@ -35,6 +35,8 @@
#define DB_E_DATAOVERFLOW 0x80040e57
+#define DB_E_MISMATCHEDPROVIDER 0x80040e75
+
#define DB_S_ERRORSOCCURRED 0x00040eda
#endif /* __WINE_OLEDBERR_H */
--
1.7.10.4
More information about the wine-patches
mailing list