Nikolay Sivov : oledb32: Partial implementation of GetDataSource().

Alexandre Julliard julliard at winehq.org
Thu Dec 27 13:02:29 CST 2012


Module: wine
Branch: master
Commit: ec4de1f9fe0f7dd4138c9d8a721515d40015aa75
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=ec4de1f9fe0f7dd4138c9d8a721515d40015aa75

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Wed Dec 26 20:53:45 2012 +0400

oledb32: Partial implementation of GetDataSource().

---

 dlls/oledb32/datainit.c       |  130 +++++++++++++++++++++++++++++++++-------
 dlls/oledb32/tests/database.c |   42 +++++++++-----
 include/oledberr.h            |    2 +
 3 files changed, 137 insertions(+), 37 deletions(-)

diff --git a/dlls/oledb32/datainit.c b/dlls/oledb32/datainit.c
index 78a005d..1316c0f 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);
+    WCHAR *prov = NULL;
+    CLSID provclsid;
+    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;
+        progid = CoTaskMemAlloc((len+1)*sizeof(WCHAR));
+        if (!progid) return E_OUTOFMEMORY;
+
+        memcpy(progid, start, len*sizeof(WCHAR));
+        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..ede1074 100644
--- a/dlls/oledb32/tests/database.c
+++ b/dlls/oledb32/tests/database.c
@@ -30,22 +30,17 @@
 
 #include "wine/test.h"
 
-
-static void test_database(void)
+static void test_GetDataSource(WCHAR *initstring)
 {
-    HRESULT hr;
-    IDBInitialize *dbinit = NULL;
     IDataInitialize *datainit = NULL;
+    IDBInitialize *dbinit = NULL;
+    HRESULT hr;
 
     hr = CoCreateInstance(&CLSID_MSDAINITIALIZE, NULL, CLSCTX_INPROC_SERVER, &IID_IDataInitialize,(void**)&datainit);
-    if(FAILED(hr))
-    {
-        win_skip("Unable to load oledb library\n");
-        return;
-    }
-
-    hr = IDataInitialize_GetDataSource(datainit, NULL, CLSCTX_INPROC_SERVER, NULL, &IID_IDBInitialize, (IUnknown **)&dbinit);
     ok(hr == S_OK, "got %08x\n", hr);
+
+    /* a failure to create data source here may indicate provider is simply not present */
+    hr = IDataInitialize_GetDataSource(datainit, NULL, CLSCTX_INPROC_SERVER, initstring, &IID_IDBInitialize, (IUnknown**)&dbinit);
     if(SUCCEEDED(hr))
     {
         IDBProperties *props = NULL;
@@ -53,16 +48,35 @@ static void test_database(void)
         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);
 }
 
+static void test_database(void)
+{
+    static WCHAR initstring_jet[] = {'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',';',0,
+         'D','a','t','a',' ','S','o','u','r','c','e','=','d','u','m','m','y',';',0};
+    static WCHAR initstring_default[] = {'D','a','t','a',' ','S','o','u','r','c','e','=','d','u','m','m','y',';',0};
+    IDataInitialize *datainit = NULL;
+    HRESULT hr;
+
+    hr = CoCreateInstance(&CLSID_MSDAINITIALIZE, NULL, CLSCTX_INPROC_SERVER, &IID_IDataInitialize,(void**)&datainit);
+    if (FAILED(hr))
+    {
+        win_skip("Unable to load oledb library\n");
+        return;
+    }
+    IDataInitialize_Release(datainit);
+
+    test_GetDataSource(NULL);
+    test_GetDataSource(initstring_jet);
+    test_GetDataSource(initstring_default);
+}
+
 START_TEST(database)
 {
     OleInitialize(NULL);
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 */




More information about the wine-cvs mailing list