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 util | jbalint | 15 Oct |