List:Commits« Previous MessageNext Message »
From:jbalint Date:October 15 2007 2:00am
Subject:Connector/ODBC 3.51 commit: r819 - in branches/guffert: driver util
View as plain text  
Modified:
   branches/guffert/driver/connect.c
   branches/guffert/util/installer.c
   branches/guffert/util/installer.h
   branches/guffert/util/stringutil.c
   branches/guffert/util/stringutil.h
Log:
added support for prompting using current ODBC setup library

Modified: branches/guffert/driver/connect.c
===================================================================
--- branches/guffert/driver/connect.c	2007-10-11 23:24:38 UTC (rev 818)
+++ branches/guffert/driver/connect.c	2007-10-15 02:00:38 UTC (rev 819)
@@ -36,6 +36,8 @@
 #endif
 
 #include "installer.h"
+#include "stringutil.h"
+#include "MYODBCUtil.h"
 
 #ifndef CLIENT_NO_SCHEMA
 # define CLIENT_NO_SCHEMA      16
@@ -395,6 +397,11 @@
   parameters, and whether or not to prompt the user for more information
   using the setup library.
 
+  NOTE: The prompting done in this function using MYODBCUTIL_DATASOURCE has
+        been observed to cause an access violation outside of our code
+        (specifically in Access after prompting, before table link list).
+        This has only been seen when setting a breakpoint on this function.
+
   @param[in]  hdbc  Handle of database connection
   @param[in]  hwnd  Window handle. May be @c NULL if no prompting will be done.
   @param[in]  szConnStrIn  The connection string
@@ -426,6 +433,8 @@
   DataSource *ds= ds_new();
   /* We may have to read driver info to find the setup library. */
   Driver *pDriver= driver_new();
+  /* Legacy setup lib, used for prompting, will be deprecated by native guis */
+  MYODBCUTIL_DATASOURCE *oldds=
MYODBCUtilAllocDataSource(MYODBCUTIL_DATASOURCE_MODE_DRIVER_CONNECT);
   BOOL bPrompt= FALSE;
   HMODULE hModule= NULL;
   unsigned long options;
@@ -474,26 +483,26 @@
   switch (fDriverCompletion)
   {
   case SQL_DRIVER_PROMPT:
-    //ds->nPrompt= MYODBCUTIL_DATASOURCE_PROMPT_PROMPT;
+    oldds->nPrompt= MYODBCUTIL_DATASOURCE_PROMPT_PROMPT;
     bPrompt= TRUE;
     break;
 
   case SQL_DRIVER_COMPLETE:
-    //ds->nPrompt= MYODBCUTIL_DATASOURCE_PROMPT_COMPLETE;
+    oldds->nPrompt= MYODBCUTIL_DATASOURCE_PROMPT_COMPLETE;
     if (myodbc_do_connect(dbc, ds) == SQL_SUCCESS)
       goto connected;
     bPrompt= TRUE;
     break;
 
   case SQL_DRIVER_COMPLETE_REQUIRED:
-    //ds->nPrompt= MYODBCUTIL_DATASOURCE_PROMPT_REQUIRED;
+    oldds->nPrompt= MYODBCUTIL_DATASOURCE_PROMPT_REQUIRED;
     if (myodbc_do_connect(dbc, ds) == SQL_SUCCESS)
       goto connected;
     bPrompt= TRUE;
     break;
 
   case SQL_DRIVER_NOPROMPT:
-    //ds->nPrompt= MYODBCUTIL_DATASOURCE_PROMPT_NOPROMPT;
+    oldds->nPrompt= MYODBCUTIL_DATASOURCE_PROMPT_NOPROMPT;
     bPrompt= FALSE;
     break;
 
@@ -520,7 +529,7 @@
 
   if (bPrompt)
   {
-    BOOL (*pFunc)(SQLHDBC, SQLHWND, DataSource *);
+    BOOL (*pFunc)(SQLHDBC, SQLHWND, MYODBCUTIL_DATASOURCE *);
 
     /*
      We can not present a prompt unless we can lookup the name of the setup
@@ -558,8 +567,8 @@
      ODBC system info. This allows someone configure for a custom setup
      interface.
     */
-    ds_set_strattr(&pDriver->name, ds->driver);
-    if (!driver_lookup(pDriver))
+    sqlwcharncpy(pDriver->lib, ds->driver, ODBCDRIVER_STRLEN);
+    if (driver_lookup(pDriver))
     {
       char sz[1024];
       sprintf(sz, "Could not find driver '%s' in system information.",
@@ -569,7 +578,7 @@
       goto error;
     }
 
-    if (!pDriver->setup_lib)
+    if (!*pDriver->setup_lib)
 #endif
     {
       rc= set_dbc_error(hdbc, "HY000",
@@ -601,7 +610,7 @@
        for us to call.
     */
     /* TODO new name? args? */
-    pFunc= (BOOL (*)(SQLHDBC, SQLHWND, DataSource *))
+    pFunc= (BOOL (*)(SQLHDBC, SQLHWND, MYODBCUTIL_DATASOURCE *))
       GetProcAddress(hModule, "MYODBCSetupDriverConnect");
 
     if (pFunc == NULL)
@@ -621,13 +630,77 @@
       goto error;
     }
 
+    /* Copy to the legacy data source structure for prompting */
+    if (ds->name)
+      oldds->pszDSN=         _global_strdup(ds_get_utf8attr(ds->name,
&ds->name8));
+    if (ds->description)
+      oldds->pszDESCRIPTION= _global_strdup(ds_get_utf8attr(ds->description,
&ds->description8));
+    if (ds->server)
+      oldds->pszSERVER=      _global_strdup(ds_get_utf8attr(ds->server,
&ds->server8));
+    if (ds->uid)
+      oldds->pszUSER=        _global_strdup(ds_get_utf8attr(ds->uid,
&ds->uid8));
+    if (ds->pwd)
+      oldds->pszPASSWORD=    _global_strdup(ds_get_utf8attr(ds->pwd,
&ds->pwd8));
+    if (ds->database)
+      oldds->pszDATABASE=    _global_strdup(ds_get_utf8attr(ds->database,
&ds->database8));
+    if (ds->socket)
+      oldds->pszSOCKET=      _global_strdup(ds_get_utf8attr(ds->socket,
&ds->socket8));
+    if (ds->initstmt)
+      oldds->pszSTMT=        _global_strdup(ds_get_utf8attr(ds->initstmt,
&ds->initstmt8));
+    if (ds->option)
+      oldds->pszOPTION=      _global_strdup(ds_get_utf8attr(ds->option,
&ds->option8));
+    if (ds->sslkey)
+      oldds->pszSSLKEY=      _global_strdup(ds_get_utf8attr(ds->sslkey,
&ds->sslkey8));
+    if (ds->sslcert)
+      oldds->pszSSLCERT=     _global_strdup(ds_get_utf8attr(ds->sslcert,
&ds->sslcert8));
+    if (ds->sslca)
+      oldds->pszSSLCA=       _global_strdup(ds_get_utf8attr(ds->sslca,
&ds->sslca8));
+    if (ds->sslcapath)
+      oldds->pszSSLCAPATH=   _global_strdup(ds_get_utf8attr(ds->sslcapath,
&ds->sslcapath8));
+    if (ds->sslcipher)
+      oldds->pszSSLCIPHER=   _global_strdup(ds_get_utf8attr(ds->sslcipher,
&ds->sslcipher8));
+    if (ds->charset)
+      oldds->pszCHARSET=     _global_strdup(ds_get_utf8attr(ds->charset,
&ds->charset8));
+    oldds->pszPORT= _global_strdup("        ");
+    sprintf(oldds->pszPORT, "%d", ds->port);
+
     /* Prompt. Function returns false if user cancels.  */
-    if (!pFunc(hdbc, hwnd, ds))
+    if (!pFunc(hdbc, hwnd, oldds))
     {
       set_dbc_error(hdbc, "HY000", "User cancelled.", 0);
       rc= SQL_ERROR;
       goto error;
     }
+
+    /* After prompting, copy data back from legacy datasource struct */
+    if (oldds->pszSERVER)
+      ds_setattr_from_utf8(&ds->server, oldds->pszSERVER);
+    if (oldds->pszUSER)
+      ds_setattr_from_utf8(&ds->uid, oldds->pszUSER);
+    if (oldds->pszPASSWORD)
+      ds_setattr_from_utf8(&ds->pwd, oldds->pszPASSWORD);
+    if (oldds->pszDATABASE)
+      ds_setattr_from_utf8(&ds->database, oldds->pszDATABASE);
+    if (oldds->pszSOCKET)
+      ds_setattr_from_utf8(&ds->socket, oldds->pszSOCKET);
+    if (oldds->pszSTMT)
+      ds_setattr_from_utf8(&ds->initstmt, oldds->pszSTMT);
+    if (oldds->pszOPTION)
+      ds_setattr_from_utf8(&ds->option, oldds->pszOPTION);
+    if (oldds->pszSSLKEY)
+      ds_setattr_from_utf8(&ds->sslkey, oldds->pszSSLKEY);
+    if (oldds->pszSSLCERT)
+      ds_setattr_from_utf8(&ds->sslcert, oldds->pszSSLCERT);
+    if (oldds->pszSSLCA)
+      ds_setattr_from_utf8(&ds->sslca, oldds->pszSSLCA);
+    if (oldds->pszSSLCAPATH)
+      ds_setattr_from_utf8(&ds->sslcapath, oldds->pszSSLCAPATH);
+    if (oldds->pszSSLCIPHER)
+      ds_setattr_from_utf8(&ds->sslcipher, oldds->pszSSLCIPHER);
+    if (oldds->pszCHARSET)
+      ds_setattr_from_utf8(&ds->charset, oldds->pszCHARSET);
+    if (oldds->pszPORT)
+      ds->port= strtoul(oldds->pszPORT, NULL, 10);
   }
 
   if ((rc= myodbc_do_connect(dbc, ds)) != SQL_SUCCESS)
@@ -669,6 +742,7 @@
 
   driver_delete(pDriver);
   ds_delete(ds);
+  MYODBCUtilFreeDataSource(oldds);
 
   return rc;
 }

Modified: branches/guffert/util/installer.c
===================================================================
--- branches/guffert/util/installer.c	2007-10-11 23:24:38 UTC (rev 818)
+++ branches/guffert/util/installer.c	2007-10-15 02:00:38 UTC (rev 819)
@@ -190,6 +190,49 @@
 
 
 /*
+ * Lookup a driver given only the filename of the driver. This is used
+ * to support prompting for additional DSN info upon connect when the
+ * driver uses an external setup library.
+ */
+int driver_lookup_name(Driver *driver)
+{
+  SQLWCHAR drivers[1024];
+  SQLWCHAR *pdrv= drivers;
+  SQLWCHAR driverinfo[1024];
+  int len;
+  short slen; /* WORD needed for windows */
+
+  /* get list of drivers */
+#ifdef _WIN32
+  if (!SQLGetInstalledDriversW(pdrv, 1023, &slen) || !(len= slen))
+#else
+  if (!(len= SQLGetPrivateProfileStringW(NULL, NULL, W_EMPTY, pdrv,
+                                         1023, W_ODBCINST_INI)))
+#endif
+    return -1;
+
+  /* check the lib of each driver for one that matches the given lib name */
+  while (len > 0)
+  {
+    if (!SQLGetPrivateProfileStringW(pdrv, W_DRIVER, W_EMPTY, driverinfo,
+                                    1023, W_ODBCINST_INI))
+      continue;
+
+    if (!sqlwcharcasecmp(driverinfo, driver->lib))
+    {
+      sqlwcharncpy(driver->name, pdrv, ODBCDRIVER_STRLEN);
+      return 0;
+    }
+
+    len -= sqlwcharlen(pdrv) + 1;
+    pdrv += sqlwcharlen(pdrv) + 1;
+  }
+
+  return -1;
+}
+
+
+/*
  * Lookup a driver in the system. The driver name is read from the given
  * object. If greater-than zero is returned, additional information
  * can be obtained from SQLInstallerError(). A less-than zero return code
@@ -201,6 +244,13 @@
   SQLWCHAR *entries= buf;
   SQLWCHAR *dest;
 
+  /* if only the filename is given, we must get the driver's name */
+  if (!*driver->name && *driver->lib)
+  {
+    if (driver_lookup_name(driver))
+      return -1;
+  }
+
   /* get entries and make sure the driver exists */
   if (SQLGetPrivateProfileStringW(driver->name, NULL, W_EMPTY, buf, 4096,
                                   W_ODBCINST_INI) < 1)
@@ -368,6 +418,7 @@
   x_free(ds->database8);
   x_free(ds->socket8);
   x_free(ds->initstmt8);
+  x_free(ds->option8);
   x_free(ds->charset8);
   x_free(ds->sslkey8);
   x_free(ds->sslcert8);
@@ -385,8 +436,7 @@
  */
 int ds_set_strattr(SQLWCHAR **attr, const SQLWCHAR *val)
 {
-  if (*attr)
-    x_free(*attr);
+  x_free(*attr);
   if (val && *val)
     *attr= sqlwchardup(val, SQL_NTS);
   else
@@ -401,8 +451,7 @@
  */
 int ds_set_strnattr(SQLWCHAR **attr, const SQLWCHAR *val, size_t charcount)
 {
-  if (*attr)
-    x_free(*attr);
+  x_free(*attr);
 
   if (charcount == SQL_NTS)
     charcount= sqlwcharlen(val);
@@ -777,9 +826,22 @@
 SQLCHAR *ds_get_utf8attr(SQLWCHAR *attrw, SQLCHAR **attr8)
 {
   SQLINTEGER len= SQL_NTS;
-  if (*attr8)
-    x_free(*attr8);
+  x_free(*attr8);
   *attr8= sqlwchar_as_utf8(attrw, &len);
   return *attr8;
 }
 
+
+/*
+ * Assign a data source attribute from a UTF-8 string.
+ */
+int ds_setattr_from_utf8(SQLWCHAR **attr, SQLCHAR *val8)
+{
+  size_t len= strlen(val8);
+  x_free(*attr);
+  if (!(*attr= (SQLWCHAR *)my_malloc((len + 1) * sizeof(SQLWCHAR), MYF(0))))
+    return -1;
+  utf8_as_sqlwchar(*attr, len, val8, len);
+  return 0;
+}
+

Modified: branches/guffert/util/installer.h
===================================================================
--- branches/guffert/util/installer.h	2007-10-11 23:24:38 UTC (rev 818)
+++ branches/guffert/util/installer.h	2007-10-15 02:00:38 UTC (rev 819)
@@ -66,6 +66,7 @@
 
 Driver *driver_new();
 void driver_delete(Driver *driver);
+int driver_lookup_name(Driver *driver);
 int driver_lookup(Driver *driver);
 int driver_from_kvpair_semicolon(Driver *driver, const SQLWCHAR *attrs);
 int driver_to_kvpair_null(Driver *driver, SQLWCHAR *attrs, size_t attrslen);
@@ -99,6 +100,7 @@
   SQLCHAR *database8;
   SQLCHAR *socket8;
   SQLCHAR *initstmt8;
+  SQLCHAR *option8;
   SQLCHAR *charset8;
   SQLCHAR *sslkey8;
   SQLCHAR *sslcert8;
@@ -119,6 +121,7 @@
 int ds_add(DataSource *ds);
 int ds_exists(SQLWCHAR *name);
 SQLCHAR *ds_get_utf8attr(SQLWCHAR *attrw, SQLCHAR **attr8);
+int ds_setattr_from_utf8(SQLWCHAR **attr, SQLCHAR *val8);
 
 #ifdef __cplusplus
 }

Modified: branches/guffert/util/stringutil.c
===================================================================
--- branches/guffert/util/stringutil.c	2007-10-11 23:24:38 UTC (rev 818)
+++ branches/guffert/util/stringutil.c	2007-10-15 02:00:38 UTC (rev 819)
@@ -611,3 +611,19 @@
 }
 
 
+/*
+ * Copy up to 'n' characters (including NULL) from src to dest.
+ */
+SQLWCHAR *sqlwcharncpy(SQLWCHAR *dest, const SQLWCHAR *src, size_t n)
+{
+  if (!dest || !src)
+    return NULL;
+  while (*src && n--)
+    *dest++= *src++;
+  if (n)
+    *dest= 0;
+  else
+    *(dest - 1)= 0;
+  return dest;
+}
+

Modified: branches/guffert/util/stringutil.h
===================================================================
--- branches/guffert/util/stringutil.h	2007-10-11 23:24:38 UTC (rev 818)
+++ branches/guffert/util/stringutil.h	2007-10-15 02:00:38 UTC (rev 819)
@@ -93,6 +93,7 @@
 unsigned long sqlwchartoul(const SQLWCHAR *wstr);
 void sqlwcharfromul(SQLWCHAR *wstr, unsigned long v);
 size_t sqlwcharncat2(SQLWCHAR *dest, const SQLWCHAR *src, size_t *n);
+SQLWCHAR *sqlwcharncpy(SQLWCHAR *dest, const SQLWCHAR *src, size_t n);
 
 
 #endif /* _STRINGUTIL_H */

Thread
Connector/ODBC 3.51 commit: r819 - in branches/guffert: driver utiljbalint15 Oct