1 /*
2  *  connect.c
3  *
4  *  $Id$
5  *
6  *  Connect (load) driver
7  *
8  *  The iODBC driver manager.
9  *
10  *  Copyright (C) 1995 Ke Jin <kejin@empress.com>
11  *  Copyright (C) 1996-2021 OpenLink Software <iodbc@openlinksw.com>
12  *  All Rights Reserved.
13  *
14  *  This software is released under the terms of either of the following
15  *  licenses:
16  *
17  *      - GNU Library General Public License (see LICENSE.LGPL)
18  *      - The BSD License (see LICENSE.BSD).
19  *
20  *  Note that the only valid version of the LGPL license as far as this
21  *  project is concerned is the original GNU Library General Public License
22  *  Version 2, dated June 1991.
23  *
24  *  While not mandated by the BSD license, any patches you make to the
25  *  iODBC source code may be contributed back into the iODBC project
26  *  at your discretion. Contributions will benefit the Open Source and
27  *  Data Access community as a whole. Submissions may be made at:
28  *
29  *      http://www.iodbc.org
30  *
31  *
32  *  GNU Library Generic Public License Version 2
33  *  ============================================
34  *  This library is free software; you can redistribute it and/or
35  *  modify it under the terms of the GNU Library General Public
36  *  License as published by the Free Software Foundation; only
37  *  Version 2 of the License dated June 1991.
38  *
39  *  This library is distributed in the hope that it will be useful,
40  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
41  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
42  *  Library General Public License for more details.
43  *
44  *  You should have received a copy of the GNU Library General Public
45  *  License along with this library; if not, write to the Free
46  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
47  *
48  *
49  *  The BSD License
50  *  ===============
51  *  Redistribution and use in source and binary forms, with or without
52  *  modification, are permitted provided that the following conditions
53  *  are met:
54  *
55  *  1. Redistributions of source code must retain the above copyright
56  *     notice, this list of conditions and the following disclaimer.
57  *  2. Redistributions in binary form must reproduce the above copyright
58  *     notice, this list of conditions and the following disclaimer in
59  *     the documentation and/or other materials provided with the
60  *     distribution.
61  *  3. Neither the name of OpenLink Software Inc. nor the names of its
62  *     contributors may be used to endorse or promote products derived
63  *     from this software without specific prior written permission.
64  *
65  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
66  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
67  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
68  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OPENLINK OR
69  *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
70  *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
71  *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
72  *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
73  *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
74  *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
75  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
76  */
77 
78 #include <iodbc.h>
79 
80 #include <assert.h>
81 #include <sql.h>
82 #include <sqlext.h>
83 #include <sqlucode.h>
84 #include <iodbcext.h>
85 #include <odbcinst.h>
86 
87 #include "dlproc.h"
88 
89 #include "unicode.h"
90 #include "herr.h"
91 #include "henv.h"
92 #include "hdbc.h"
93 #include "hstmt.h"
94 
95 #include "itrace.h"
96 
97 #include "unicode.h"
98 
99 #if defined (__APPLE__) && !defined (NO_FRAMEWORKS)
100 #include <Carbon/Carbon.h>
101 #endif
102 
103 #include "misc.h"
104 #include "iodbc_misc.h"
105 
106 /*
107  *  Identification strings
108  */
109 static char sccsid[] = "@(#)iODBC driver manager " VERSION "\n";
110 char *iodbc_version = VERSION;
111 
112 
113 /*
114  *  Prototypes
115  */
116 extern SQLRETURN _iodbcdm_driverunload (HDBC hdbc, int ver);
117 extern SQLRETURN SQL_API _iodbcdm_SetConnectOption (SQLHDBC hdbc,
118     SQLUSMALLINT fOption, SQLULEN vParam, SQLCHAR waMode);
119 
120 
121 #if 0
122 #define CHECK_DRVCONN_DIALBOX(path) \
123   { \
124     if ((handle = DLL_OPEN(path)) != NULL) \
125       { \
126         if (DLL_PROC(handle, "_iodbcdm_drvconn_dialboxw") != NULL) \
127           { \
128             DLL_CLOSE(handle); \
129             retVal = TRUE; \
130             goto quit; \
131           } \
132         else \
133           { \
134             if (DLL_PROC(handle, "_iodbcdm_drvconn_dialbox") != NULL) \
135               { \
136                 DLL_CLOSE(handle); \
137                 retVal = TRUE; \
138                 goto quit; \
139               } \
140           } \
141         DLL_CLOSE(handle); \
142       } \
143   }
144 
145 
146 
147 static BOOL
148 _iodbcdm_CheckDriverLoginDlg (
149     LPSTR drv,
150     LPSTR dsn
151 )
152 {
153   char tokenstr[4096];
154   char drvbuf[4096] = { L'\0'};
155   HDLL handle;
156   BOOL retVal = FALSE;
157 
158   /* Check if the driver is provided */
159   if (drv == NULL)
160     {
161       SQLSetConfigMode (ODBC_BOTH_DSN);
162       SQLGetPrivateProfileString ("ODBC Data Sources",
163         dsn && dsn[0] != '\0' ? dsn : "Default",
164         "", tokenstr, sizeof (tokenstr), NULL);
165       drv = tokenstr;
166     }
167 
168   /* Call the iodbcdm_drvconn_dialbox */
169 
170   SQLSetConfigMode (ODBC_USER_DSN);
171   if (!access (drv, X_OK))
172     { CHECK_DRVCONN_DIALBOX (drv); }
173   if (SQLGetPrivateProfileString (drv, "Driver", "", drvbuf,
174     sizeof (drvbuf), "odbcinst.ini"))
175     { CHECK_DRVCONN_DIALBOX (drvbuf); }
176   if (SQLGetPrivateProfileString (drv, "Setup", "", drvbuf,
177     sizeof (drvbuf), "odbcinst.ini"))
178     { CHECK_DRVCONN_DIALBOX (drvbuf); }
179   if (SQLGetPrivateProfileString ("Default", "Driver", "", drvbuf,
180     sizeof (drvbuf), "odbcinst.ini"))
181     { CHECK_DRVCONN_DIALBOX (drvbuf); }
182   if (SQLGetPrivateProfileString ("Default", "Setup", "", drvbuf,
183     sizeof (drvbuf), "odbcinst.ini"))
184     { CHECK_DRVCONN_DIALBOX (drvbuf); }
185 
186 
187   SQLSetConfigMode (ODBC_SYSTEM_DSN);
188   if (!access (drv, X_OK))
189     { CHECK_DRVCONN_DIALBOX (drv); }
190   if (SQLGetPrivateProfileString (drv, "Driver", "", drvbuf,
191     sizeof (drvbuf), "odbcinst.ini"))
192     { CHECK_DRVCONN_DIALBOX (drvbuf); }
193   if (SQLGetPrivateProfileString (drv, "Setup", "", drvbuf,
194     sizeof (drvbuf), "odbcinst.ini"))
195     { CHECK_DRVCONN_DIALBOX (drvbuf); }
196   if (SQLGetPrivateProfileString ("Default", "Driver", "", drvbuf,
197     sizeof (drvbuf), "odbcinst.ini"))
198     { CHECK_DRVCONN_DIALBOX (drvbuf); }
199   if (SQLGetPrivateProfileString ("Default", "Setup", "", drvbuf,
200     sizeof (drvbuf), "odbcinst.ini"))
201     { CHECK_DRVCONN_DIALBOX (drvbuf); }
202 
203 quit:
204 
205   return retVal;
206 }
207 #endif
208 
209 
210 #define RETURN(_ret)							\
211   do {									\
212     retcode = _ret;							\
213     goto end;								\
214   } while (0)
215 
216 
217 
218 static SQLRETURN
_iodbcdm_SetConnectOption_init(SQLHDBC hdbc,SQLUSMALLINT fOption,SQLULEN vParam,UCHAR waMode)219 _iodbcdm_SetConnectOption_init (
220     SQLHDBC		  hdbc,
221     SQLUSMALLINT	  fOption,
222     SQLULEN		  vParam,
223     UCHAR		  waMode)
224 {
225   CONN (pdbc, hdbc);
226   ENVR (penv, pdbc->henv);
227   HPROC hproc = SQL_NULL_HPROC;
228   SQLRETURN retcode = SQL_SUCCESS;
229   int retinfo = 0;
230   CONV_DIRECT conv_direct = CD_NONE;
231   DM_CONV *conv = &pdbc->conv;
232 
233   SQLINTEGER strLength = 0;
234   void *ptr = (void *) vParam;
235   void *_vParam = NULL;
236 
237   if (fOption >= 1000)
238     {
239       retinfo = 1;		/* Change SQL_ERROR -> SQL_SUCCESS_WITH_INFO */
240     }
241 
242   if (penv->unicode_driver && waMode != 'W')
243     conv_direct = CD_A2W;
244   else if (!penv->unicode_driver && waMode == 'W')
245     conv_direct = CD_W2A;
246   else if (waMode == 'W' && conv->dm_cp!=conv->drv_cp)
247     conv_direct = CD_W2W;
248 
249   switch (fOption)
250     {
251       case SQL_ATTR_TRACEFILE:
252       case SQL_CURRENT_QUALIFIER:
253       case SQL_TRANSLATE_DLL:
254       case SQL_APPLICATION_NAME:
255       case SQL_COPT_SS_ENLIST_IN_DTC:
256       case SQL_COPT_SS_PERF_QUERY_LOG:
257       case SQL_COPT_SS_PERF_DATA_LOG:
258       case SQL_CURRENT_SCHEMA:
259         if (conv_direct != CD_NONE)
260           {
261             _vParam = conv_text_m2d(conv, (void *)vParam, SQL_NTS, conv_direct);
262             ptr = _vParam;
263             strLength = SQL_NTS;
264           }
265         break;
266     }
267 
268   if (penv->unicode_driver)
269     {
270       /* SQL_XXX_W */
271       if ((hproc = _iodbcdm_getproc (pdbc, en_SetConnectOptionW))
272           != SQL_NULL_HPROC)
273         {
274           CALL_DRIVER (hdbc, pdbc, retcode, hproc,
275 	      (pdbc->dhdbc, fOption, ptr));
276         }
277 #if (ODBCVER >= 0x300)
278       else if ((hproc = _iodbcdm_getproc (pdbc, en_SetConnectAttrW))
279           != SQL_NULL_HPROC)
280         {
281           CALL_DRIVER (hdbc, pdbc, retcode, hproc,
282 	      (pdbc->dhdbc, fOption, ptr, strLength));
283         }
284 #endif
285     }
286   else
287     {
288       /* SQL_XXX */
289       /* SQL_XXX_A */
290       if ((hproc = _iodbcdm_getproc (pdbc, en_SetConnectOption))
291            != SQL_NULL_HPROC)
292         {
293           CALL_DRIVER (hdbc, pdbc, retcode, hproc,
294 	      (pdbc->dhdbc, fOption, vParam));
295         }
296       else if ((hproc = _iodbcdm_getproc (pdbc, en_SetConnectOptionA))
297            != SQL_NULL_HPROC)
298         {
299           CALL_DRIVER (hdbc, pdbc, retcode, hproc,
300 	      (pdbc->dhdbc, fOption, vParam));
301         }
302 #if (ODBCVER >= 0x300)
303       else if ((hproc = _iodbcdm_getproc (pdbc, en_SetConnectAttr))
304           != SQL_NULL_HPROC)
305         {
306           CALL_DRIVER (hdbc, pdbc, retcode, hproc,
307 	      (pdbc->dhdbc, fOption, vParam, strLength));
308         }
309       else if ((hproc = _iodbcdm_getproc (pdbc, en_SetConnectAttrA))
310           != SQL_NULL_HPROC)
311         {
312           CALL_DRIVER (hdbc, pdbc, retcode, hproc,
313 	      (pdbc->dhdbc, fOption, vParam, strLength));
314         }
315 #endif
316     }
317   MEM_FREE(_vParam);
318 
319   if (hproc == SQL_NULL_HPROC)
320     {
321       PUSHSQLERR (pdbc->herr, en_IM004);
322       return SQL_SUCCESS_WITH_INFO;
323     }
324 
325   if (retcode != SQL_SUCCESS && retinfo)
326     return SQL_SUCCESS_WITH_INFO;
327 
328   return retcode;
329 }
330 
331 
332 static SQLRETURN
_iodbcdm_SetConnectAttr_init(SQLHDBC hdbc,SQLUSMALLINT fOption,SQLULEN vParam)333 _iodbcdm_SetConnectAttr_init (
334     SQLHDBC		  hdbc,
335     SQLUSMALLINT	  fOption,
336     SQLULEN		  vParam)
337 {
338   CONN (pdbc, hdbc);
339   ENVR (penv, pdbc->henv);
340   HPROC hproc = SQL_NULL_HPROC;
341   SQLRETURN retcode = SQL_ERROR;
342   SQLINTEGER strLength = 0;
343   void *ptr = (void *) vParam;
344 
345 
346   if (penv->unicode_driver)
347     {
348 #if (ODBCVER >= 0x300)
349       if ((hproc = _iodbcdm_getproc (pdbc, en_SetConnectAttrW))
350           != SQL_NULL_HPROC)
351         {
352           CALL_DRIVER (hdbc, pdbc, retcode, hproc,
353 	      (pdbc->dhdbc, fOption, ptr, strLength));
354         }
355 #endif
356     }
357   else
358     {
359 #if (ODBCVER >= 0x300)
360       if ((hproc = _iodbcdm_getproc (pdbc, en_SetConnectAttr))
361           != SQL_NULL_HPROC)
362         {
363           CALL_DRIVER (hdbc, pdbc, retcode, hproc,
364 	      (pdbc->dhdbc, fOption, vParam, strLength));
365         }
366       else if ((hproc = _iodbcdm_getproc (pdbc, en_SetConnectAttrA))
367           != SQL_NULL_HPROC)
368         {
369           CALL_DRIVER (hdbc, pdbc, retcode, hproc,
370 	      (pdbc->dhdbc, fOption, vParam, strLength));
371         }
372 #endif
373     }
374 
375   return retcode;
376 }
377 
378 
379 
380 static SQLRETURN
_iodbcdm_getInfo_init(SQLHDBC hdbc,SQLUSMALLINT fInfoType,SQLPOINTER rgbInfoValue,SQLSMALLINT cbInfoValueMax,SQLSMALLINT * pcbInfoValue,SQLCHAR waMode)381 _iodbcdm_getInfo_init (SQLHDBC hdbc,
382     SQLUSMALLINT fInfoType,
383     SQLPOINTER rgbInfoValue,
384     SQLSMALLINT cbInfoValueMax,
385     SQLSMALLINT * pcbInfoValue,
386     SQLCHAR waMode)
387 {
388   CONN (pdbc, hdbc);
389   ENVR (penv, pdbc->henv);
390   HPROC hproc = SQL_NULL_HPROC;
391   SQLRETURN retcode = SQL_SUCCESS;
392 
393   waMode = waMode; /*UNUSED*/
394 
395   switch(fInfoType)
396     {
397       case SQL_CURSOR_COMMIT_BEHAVIOR:
398       case SQL_CURSOR_ROLLBACK_BEHAVIOR:
399         break;
400       default:
401         return SQL_ERROR;
402     }
403 
404   CALL_UDRIVER(hdbc, pdbc, retcode, hproc, penv->unicode_driver,
405     en_GetInfo, (
406        pdbc->dhdbc,
407        fInfoType,
408        rgbInfoValue,
409        cbInfoValueMax,
410        pcbInfoValue));
411 
412   if (hproc == SQL_NULL_HPROC)
413     {
414       PUSHSQLERR (pdbc->herr, en_IM004);
415       return SQL_SUCCESS_WITH_INFO;
416     }
417 
418   return retcode;
419 }
420 
421 
422 static SQLRETURN
_iodbcdm_finish_disconnect(HDBC hdbc,BOOL driver_disconnect)423 _iodbcdm_finish_disconnect (HDBC hdbc, BOOL driver_disconnect)
424 {
425   CONN (pdbc, hdbc);
426   HPROC hproc = SQL_NULL_HPROC;
427 
428   DPRINTF ((stderr,
429       "DEBUG: _iodbcdm_finish_disconnect (conn %p, driver_disconnect %d)\n",
430       hdbc, driver_disconnect));
431 
432   if (driver_disconnect)
433     {
434       SQLRETURN retcode;
435 
436       hproc = _iodbcdm_getproc (pdbc, en_Disconnect);
437       if (hproc == SQL_NULL_HPROC)
438         {
439           PUSHSQLERR (pdbc->herr, en_IM001);
440           return SQL_ERROR;
441         }
442 
443       ODBC_UNLOCK ();
444       CALL_DRIVER (hdbc, pdbc, retcode, hproc, (pdbc->dhdbc));
445       ODBC_LOCK ();
446 
447       if (!SQL_SUCCEEDED (retcode))
448         {
449           /* diff from MS specs. We disallow
450            * driver SQLDisconnect() return
451            * SQL_SUCCESS_WITH_INFO and post
452            * error message.
453            */
454           return retcode;
455         }
456     }
457 
458   /* free all statement handle(s) on this connection */
459   while (pdbc->hstmt != NULL)
460     _iodbcdm_dropstmt (pdbc->hstmt);
461 
462   /* state transition */
463   pdbc->state = en_dbc_allocated;
464 
465   return SQL_SUCCESS;
466 }
467 
468 
469 #if (ODBCVER >= 0x300)
470 /*
471  * Set Retry Wait timeout
472  */
473 static void
_iodbcdm_pool_set_retry_wait(HDBC hdbc)474 _iodbcdm_pool_set_retry_wait (HDBC hdbc)
475 {
476   CONN (pdbc, hdbc);
477   int retry_wait = 0;
478   char buf[1024];
479 
480   /* Get the "Retry Wait" keyword value from the Pooling section */
481   SQLSetConfigMode (ODBC_BOTH_DSN);
482   if (SQLGetPrivateProfileString ("ODBC Connection Pooling", "Retry Wait", "",
483          buf, sizeof (buf), "odbcinst.ini") != 0 &&
484          buf[0] != '\0')
485     retry_wait = atoi(buf);
486 
487   DPRINTF ((stderr, "DEBUG: setting RetryWait %d (conn %p)\n",
488       retry_wait, hdbc));
489   pdbc->cp_retry_wait = time(NULL) + retry_wait;
490 }
491 
492 
493 extern SQLRETURN SQLFreeConnect_Internal (SQLHDBC hdbc);
494 
495 /*
496  * Drop connection from the pool
497  */
498 void
_iodbcdm_pool_drop_conn(HDBC hdbc,HDBC hdbc_prev)499 _iodbcdm_pool_drop_conn (HDBC hdbc, HDBC hdbc_prev)
500 {
501   CONN (pdbc, hdbc);
502   CONN (pdbc_prev, hdbc_prev);
503 
504   assert (!pdbc->cp_in_use);
505 
506   DPRINTF ((stderr, "DEBUG: dropping connection %p (prev %p) from the pool\n",
507       hdbc, hdbc_prev));
508 
509   /* remove from pool */
510   if (pdbc_prev != NULL)
511     pdbc_prev->next = pdbc->next;
512   else
513     {
514       GENV (genv, pdbc->genv);
515 
516       genv->pdbc_pool = pdbc->next;
517     }
518 
519   /* finish disconnect and free connection */
520   _iodbcdm_finish_disconnect (hdbc, TRUE);
521   SQLFreeConnect_Internal (hdbc);
522   MEM_FREE (hdbc);
523 }
524 
525 
526 /*
527  * Copy connection parameters from src to dst and reset src parameters
528  * so that src can be correctly freed by SQLDisconnect.
529  */
530 static void
_iodbcdm_pool_copy_conn(HDBC hdbc_dst,HDBC hdbc_src)531 _iodbcdm_pool_copy_conn (HDBC hdbc_dst, HDBC hdbc_src)
532 {
533   CONN (pdbc_dst, hdbc_dst);
534   CONN (pdbc_src, hdbc_src);
535   HDBC next;
536   time_t cp_timeout, cp_expiry_time;
537 
538   /* Preserve `next', `cp_timeout' and `cp_expiry_time' */
539   next = pdbc_dst->next;
540   cp_timeout = pdbc_dst->cp_timeout;
541   cp_expiry_time = pdbc_dst->cp_expiry_time;
542   *pdbc_dst = *pdbc_src;
543   pdbc_dst->next = next;
544   pdbc_dst->cp_timeout = cp_timeout;
545   pdbc_dst->cp_expiry_time = cp_expiry_time;
546 
547   /* Reset parameters of source connection */
548   pdbc_src->herr = SQL_NULL_HERR;
549   pdbc_src->dhdbc = SQL_NULL_HDBC;
550   pdbc_src->henv = SQL_NULL_HENV;
551   pdbc_src->hstmt = SQL_NULL_HSTMT;
552   pdbc_src->hdesc = SQL_NULL_HDESC;
553   pdbc_src->current_qualifier = NULL;
554   pdbc_src->drvopt = NULL;
555 
556   pdbc_src->cp_probe = NULL;
557   pdbc_src->cp_dsn = NULL;
558   pdbc_src->cp_uid = NULL;
559   pdbc_src->cp_pwd = NULL;
560   pdbc_src->cp_connstr = NULL;
561 }
562 
563 
564 /*
565  * Check if attributes of two connections match
566  */
567 static BOOL
_iodbcdm_pool_check_attr_match(HDBC hdbc,HDBC cp_hdbc)568 _iodbcdm_pool_check_attr_match (HDBC hdbc, HDBC cp_hdbc)
569 {
570   CONN (pdbc, hdbc);
571   GENV (genv, pdbc->genv);
572   CONN (cp_pdbc, cp_hdbc);
573   BOOL strict_match = (genv->cp_match == SQL_CP_STRICT_MATCH);
574 
575   DPRINTF ((stderr, "DEBUG: check attr match (conn %p, cp_conn %p)\n",
576       hdbc, cp_hdbc));
577 
578   /*
579    * Check attrs that must be set before connection has been made:
580    * - SQL_ATTR_PACKET_SIZE (packet_size)
581    * - SQL_ATTR_ODBC_CURSORS (odbc_cursors)
582    *
583    * SQL_ATTR_PACKET_SIZE can be different if !strict_match.
584    * The value of SQL_ATTR_LOGIN_TIMEOUT is not examined.
585    */
586   if (strict_match && pdbc->packet_size != cp_pdbc->packet_size)
587     {
588       DPRINTF ((stderr, "DEBUG: packet_size does not match (conn %p, cp_conn %p, strict_match %d)",
589         hdbc, cp_hdbc, strict_match));
590       return FALSE;
591     }
592 
593   if (pdbc->odbc_cursors != cp_pdbc->odbc_cursors)
594     {
595       DPRINTF ((stderr, "DEBUG: odbc_cursors does not match (conn %p, cp_conn %p, strict_match %d)",
596         hdbc, cp_hdbc, strict_match));
597       return FALSE;
598     }
599 
600   if (pdbc->conv.dm_cp != cp_pdbc->conv.dm_cp || pdbc->conv.drv_cp != cp_pdbc->conv.drv_cp)
601     {
602       DPRINTF ((stderr, "DEBUG: unicode mode does not match (conn %p, cp_conn %p)",
603         hdbc, cp_hdbc));
604       return FALSE;
605     }
606 
607   /*
608    * Check attrs that must be set either before or after the connection
609    * has been made:
610    * - SQL_ATTR_ACCESS_MODE (access_mode, default SQL_MODE_DEFAULT)
611    * - SQL_ATTR_AUTOCOMMIT (autocommit, default SQL_AUTOCOMMIT_DEFAULT)
612    * - SQL_ATTR_CURRENT_CATALOG (current_qualifier)
613    * - SQL_ATTR_QUIET_MODE (quiet_mode)
614    * - SQL_ATTR_TXN_ISOLATION (txn_isolation, default SQL_TXN_READ_UNCOMMITTED)
615    *
616    * If an attr is not set by the application but set in the pool:
617    * - if there is a default, an attr is reset to the default value
618    * (see _iodbcdm_pool_reset_conn_attrs()).
619    * - if there is no default value, pooled connection is not considered
620    * a match
621    *
622    * If an attr is set by the application, this value overrides the
623    * value from the pool.
624    */
625   if (pdbc->current_qualifier == NULL && cp_pdbc->current_qualifier != NULL)
626     {
627       /* has not been set by application, but set in the pool */
628       DPRINTF ((stderr, "DEBUG: current_qualifier has not been set by application, but is set in the pool (conn %p, cp_conn %p)",
629         hdbc, cp_hdbc));
630       return FALSE;
631     }
632 
633   if (pdbc->quiet_mode == 0 && cp_pdbc->quiet_mode != 0)
634     {
635       /* has not been set by application, but set in the pool */
636       DPRINTF ((stderr, "DEBUG: quiet_mode has not been set by application, but is set in the pool (conn %p, cp_conn %p)",
637         hdbc, cp_hdbc));
638       return FALSE;
639     }
640 
641   return TRUE;
642 }
643 
644 
645 /*
646  * Reset connection attributes to the default values (if an attr is not set
647  * by application and there is a default) or to the value set by application.
648  */
649 SQLRETURN
_iodbcdm_pool_reset_conn_attrs(SQLHDBC hdbc,SQLHDBC cp_hdbc)650 _iodbcdm_pool_reset_conn_attrs (SQLHDBC hdbc, SQLHDBC cp_hdbc)
651 {
652   CONN (pdbc, hdbc);
653   CONN (cp_pdbc, cp_hdbc);
654   SQLRETURN retcode = SQL_SUCCESS;
655   SQLRETURN ret;
656 
657   if (pdbc->access_mode != cp_pdbc->access_mode)
658     {
659       cp_pdbc->access_mode = pdbc->access_mode;
660 
661       ret = _iodbcdm_SetConnectOption_init (
662           cp_pdbc, SQL_ACCESS_MODE, cp_pdbc->access_mode, 'A');
663       retcode |= ret;
664     }
665 
666   if (pdbc->autocommit != cp_pdbc->autocommit)
667     {
668       cp_pdbc->autocommit = pdbc->autocommit;
669 
670       ret = _iodbcdm_SetConnectOption_init (
671 	  cp_pdbc, SQL_AUTOCOMMIT, cp_pdbc->autocommit, 'A');
672       retcode |= ret;
673     }
674 
675   if (pdbc->current_qualifier != NULL)
676     {
677       if (cp_pdbc->current_qualifier != NULL)
678         MEM_FREE (cp_pdbc->current_qualifier);
679       cp_pdbc->current_qualifier = pdbc->current_qualifier;
680       pdbc->current_qualifier = NULL;
681       cp_pdbc->current_qualifier_WA = pdbc->current_qualifier_WA;
682 
683       ret = _iodbcdm_SetConnectOption_init (
684           cp_pdbc, SQL_CURRENT_QUALIFIER,
685 	  (SQLULEN) cp_pdbc->current_qualifier, cp_pdbc->current_qualifier_WA);
686       retcode |= ret;
687     }
688 
689   if (cp_pdbc->quiet_mode != pdbc->quiet_mode)
690     {
691       cp_pdbc->quiet_mode = pdbc->quiet_mode;
692 
693       ret = _iodbcdm_SetConnectOption_init (
694 	  cp_pdbc, SQL_QUIET_MODE, cp_pdbc->quiet_mode, 'A');
695       retcode |= ret;
696     }
697 
698   if (pdbc->txn_isolation != cp_pdbc->txn_isolation)
699     {
700       cp_pdbc->txn_isolation = pdbc->txn_isolation;
701 
702       ret = _iodbcdm_SetConnectOption_init (
703           cp_pdbc, SQL_TXN_ISOLATION, cp_pdbc->txn_isolation, 'A');
704       retcode |= ret;
705     }
706 
707   return retcode;
708 }
709 
710 
711 extern SQLRETURN
712 SQLAllocStmt_Internal (SQLHDBC hdbc, SQLHSTMT *phstmt);
713 extern SQLRETURN
714 SQLFreeStmt_Internal (SQLHSTMT hstmt, SQLUSMALLINT fOption);
715 extern SQLRETURN SQL_API
716 SQLExecDirect_Internal (SQLHSTMT hstmt,
717     SQLPOINTER szSqlStr, SQLINTEGER cbSqlStr, SQLCHAR waMode);
718 extern SQLRETURN SQLFetch_Internal (SQLHSTMT hstmt);
719 
720 /*
721  * Execute CPProbe statement to check if connection is dead
722  */
723 static SQLRETURN
_iodbcdm_pool_exec_cpprobe(HDBC hdbc,char * cp_probe)724 _iodbcdm_pool_exec_cpprobe (HDBC hdbc, char *cp_probe)
725 {
726   HSTMT hstmt = SQL_NULL_HSTMT;
727   SQLRETURN retcode;
728   SQLSMALLINT num_cols;
729 
730   DPRINTF ((stderr, "DEBUG: executing CPProbe (conn %p, stmt [%s])\n",
731       hdbc, cp_probe));
732 
733   /* allocate statement handle */
734   retcode = SQLAllocStmt_Internal (hdbc, &hstmt);
735   if (!SQL_SUCCEEDED (retcode))
736     RETURN (retcode);
737 
738   /* execute statement */
739   retcode = SQLExecDirect_Internal (hstmt, cp_probe, SQL_NTS, 'A');
740   if (!SQL_SUCCEEDED (retcode))
741     RETURN (retcode);
742 
743   /* check that there is a result set */
744   retcode = _iodbcdm_NumResultCols (hstmt, &num_cols);
745   if (!SQL_SUCCEEDED (retcode))
746     RETURN (retcode);
747 
748   /* if there was no result set -- success */
749   if (num_cols == 0)
750     RETURN (SQL_SUCCESS);
751 
752   /* fetch results */
753   do
754     {
755       retcode = SQLFetch_Internal (hstmt);
756       if (!SQL_SUCCEEDED (retcode))
757         RETURN (retcode);
758     }
759   while (retcode != SQL_NO_DATA);
760 
761   /* success */
762   RETURN (SQL_SUCCESS);
763 
764 end:
765   if (hstmt != SQL_NULL_HSTMT)
766     SQLFreeStmt_Internal (hstmt, SQL_DROP);
767   return retcode;
768 }
769 
770 
771 /*
772  * Check if connection is dead
773  */
774 static BOOL
_iodbcdm_pool_conn_dead(HDBC hdbc)775 _iodbcdm_pool_conn_dead (HDBC hdbc)
776 {
777   CONN (pdbc, hdbc);
778   HPROC hproc = SQL_NULL_HPROC;
779   SQLRETURN retcode;
780   SQLINTEGER attr_dead;
781 
782   DPRINTF ((stderr, "DEBUG: checking if connection is dead (conn %p)\n",
783       hdbc));
784 
785   /* first try SQLGetConnectAttr */
786   CALL_UDRIVER(pdbc, pdbc, retcode, hproc, 'A', en_GetConnectAttr,
787       (pdbc->dhdbc, SQL_ATTR_CONNECTION_DEAD, &attr_dead, 0, NULL));
788   if (hproc != SQL_NULL_HPROC && SQL_SUCCEEDED (retcode))
789     {
790       DPRINTF ((stderr, "DEBUG: GetConnectAttr: attr_dead = %ld (conn %p)\n",
791           attr_dead, hdbc));
792       return attr_dead == SQL_CD_TRUE;
793     }
794 
795   /* try SQLGetConnectOption */
796   CALL_UDRIVER(pdbc, pdbc, retcode, hproc, 'A', en_GetConnectOption,
797       (pdbc->dhdbc, SQL_ATTR_CONNECTION_DEAD, &attr_dead));
798   if (hproc != SQL_NULL_HPROC && SQL_SUCCEEDED (retcode))
799     {
800       DPRINTF ((stderr, "DEBUG: GetConnectOption: attr_dead = %ld (conn %p)\n",
801           attr_dead, hdbc));
802       return attr_dead == SQL_CD_TRUE;
803     }
804 
805   /* try CPProbe statement */
806   if (pdbc->cp_probe != NULL && STRLEN(pdbc->cp_probe) > 0)
807     {
808       retcode = _iodbcdm_pool_exec_cpprobe (pdbc, pdbc->cp_probe);
809       return SQL_SUCCEEDED (retcode);
810     }
811 
812   /* don't know, assume it is alive */
813   return FALSE;
814 }
815 
816 
817 /*
818  * Get the connection from to the pool
819  *
820  * Returns 0 if the connection was put successfully
821  * Returns -1 otherwise
822  */
823 static SQLRETURN
_iodbcdm_pool_get_conn(HDBC hdbc,char * dsn,char * uid,char * pwd,char * connstr)824 _iodbcdm_pool_get_conn (
825     HDBC hdbc, char *dsn, char *uid, char *pwd, char *connstr)
826 {
827   CONN (pdbc, hdbc);
828   GENV (genv, pdbc->genv);
829   DBC_t *cp_pdbc, *cp_pdbc_next, *cp_pdbc_prev = NULL;
830   time_t current_time;
831 
832   DPRINTF ((stderr, "DEBUG: getting connection %p from the pool (dsn [%s], uid [%s], pwd [%s], connstr [%s])\n",
833       hdbc, dsn, uid, pwd, connstr));
834 
835   current_time = time(NULL);
836 
837   for (cp_pdbc = genv->pdbc_pool; cp_pdbc != NULL;
838        cp_pdbc_prev = cp_pdbc, cp_pdbc = cp_pdbc_next)
839     {
840       SQLRETURN retcode;
841 
842       cp_pdbc_next = cp_pdbc->next;
843 
844       /* skip connections in use */
845       if (cp_pdbc->cp_in_use)
846         {
847 	  DPRINTF ((stderr, "DEBUG: skipping connection %p (in use)\n",
848             cp_pdbc));
849 	  continue;
850 	}
851 
852       /*
853        * Check that pooled connection timeout has not expired
854        */
855       if (current_time >= cp_pdbc->cp_expiry_time)
856         {
857 	  DPRINTF ((stderr, "DEBUG: connection %p expired (cp_expiry_time %d, current_time %d)\n",
858             cp_pdbc, cp_pdbc->cp_expiry_time, current_time));
859 	  _iodbcdm_pool_drop_conn (cp_pdbc, cp_pdbc_prev);
860           cp_pdbc = cp_pdbc_prev;
861 	  continue;
862         }
863 
864       /*
865        * Check that requested dsn, uid, pwd and connstr match
866        * pooled connection
867        */
868       if (dsn != NULL)
869         {
870           if (cp_pdbc->cp_dsn == NULL ||
871               strcmp (dsn, cp_pdbc->cp_dsn) != 0)
872             continue;
873 	}
874       else if (cp_pdbc->cp_dsn != NULL)
875         continue;
876       if (uid != NULL)
877         {
878           if (cp_pdbc->cp_uid == NULL ||
879               strcmp (uid, cp_pdbc->cp_uid) != 0)
880             continue;
881         }
882       else if (cp_pdbc->cp_uid != NULL)
883         continue;
884       if (pwd != NULL)
885         {
886           if (cp_pdbc->cp_pwd == NULL ||
887               strcmp (pwd, cp_pdbc->cp_pwd) != 0)
888             continue;
889         }
890       else if (cp_pdbc->cp_pwd != NULL)
891         continue;
892       if (connstr != NULL)
893         {
894           if (cp_pdbc->cp_connstr == NULL ||
895               strcmp (connstr, cp_pdbc->cp_connstr) != 0)
896             continue;
897         }
898       else if (cp_pdbc->cp_connstr != NULL)
899         continue;
900 
901       DPRINTF ((stderr, "DEBUG: found matching pooled connection %p\n",
902           cp_pdbc));
903 
904       /* check that connection attributes match */
905       if (!_iodbcdm_pool_check_attr_match (pdbc, cp_pdbc))
906 	continue;
907 
908       /*
909        * Match found!
910        */
911 
912       /*
913        * Check Retry Wait timeout
914        */
915       if (cp_pdbc->cp_retry_wait != 0)
916 	{
917 	  if (current_time < cp_pdbc->cp_retry_wait)
918 	    {
919 	      /* Retry Wait timeout has not expired yet */
920               DPRINTF ((stderr,
921 		  "DEBUG: RetryWait timeout has not expired yet (cp_pdbc %p, cp_retry_wait %d, current_time %d)\n",
922                   cp_pdbc, cp_pdbc->cp_retry_wait, current_time));
923 
924               /* remember matching pooled connection */
925 	      pdbc->cp_pdbc = cp_pdbc;
926 
927 	      return SQL_ERROR;
928 	    }
929 
930           DPRINTF ((stderr, "DEBUG: RetryWait timeout reset (cp_pdbc %p)\n",
931              cp_pdbc));
932           /* reset Retry Wait timeout */
933           cp_pdbc->cp_retry_wait = 0;
934         }
935 
936       /*
937        * Check if connection is dead
938        */
939       if (_iodbcdm_pool_conn_dead (cp_pdbc))
940         {
941 	  /* Connection is dead -- try to reconnect */
942           DPRINTF ((stderr, "DEBUG: pooled connection is dead (cp_pdbc %p)\n",
943              cp_pdbc));
944 
945           /* remember matching pooled connection */
946 	  pdbc->cp_pdbc = cp_pdbc;
947           cp_pdbc->cp_in_use = TRUE;
948 
949 	  return SQL_ERROR;
950         }
951 
952       /* reset connection attrs */
953       retcode = _iodbcdm_pool_reset_conn_attrs (pdbc, cp_pdbc);
954       if (retcode != SQL_SUCCESS)
955         retcode = SQL_SUCCESS_WITH_INFO;
956 
957       /* copy parameters */
958       _iodbcdm_pool_copy_conn (pdbc, cp_pdbc);
959 
960       /* remember matching pooled connection */
961       pdbc->cp_pdbc = cp_pdbc;
962       cp_pdbc->cp_in_use = TRUE;
963 
964       DPRINTF ((stderr, "DEBUG: got connection from the pool (cp_pdbc %p)\n",
965           cp_pdbc));
966       /* found a connection in a pool */
967       return retcode;
968     }
969 
970   DPRINTF ((stderr, "DEBUG: no matching connection in the pool\n"));
971   /* can't find a connection in a pool */
972   return SQL_ERROR;
973 }
974 
975 
976 /*
977  * Put the connection back to the pool
978  *
979  * Return 0 if the connection was put successfully
980  * Return -1 otherwise
981  */
982 static int
_iodbcdm_pool_put_conn(HDBC hdbc)983 _iodbcdm_pool_put_conn (HDBC hdbc)
984 {
985   CONN (pdbc, hdbc);
986   GENV (genv, NULL);
987   DBC_t *cp_pdbc = pdbc->cp_pdbc;
988 
989   DPRINTF ((stderr, "DEBUG: putting connection back to the pool (conn %p, dsn [%s], uid [%s], pwd [%s], connstr [%s])\n",
990       hdbc, pdbc->cp_dsn, pdbc->cp_uid, pdbc->cp_pwd, pdbc->cp_connstr));
991 
992   if (cp_pdbc == NULL)
993     {
994       cp_pdbc = (DBC_t *) MEM_ALLOC (sizeof (DBC_t));
995       if (cp_pdbc == NULL)
996         {
997 	  return -1;
998 	}
999 
1000       /* put to the pool */
1001       genv = (GENV_t *) pdbc->genv;
1002       cp_pdbc->next = genv->pdbc_pool;
1003       genv->pdbc_pool = cp_pdbc;
1004 
1005       cp_pdbc->cp_timeout = pdbc->cp_timeout;
1006       DPRINTF ((stderr, "DEBUG: new pooled connection %p\n", cp_pdbc));
1007     }
1008 
1009   /* copy out parameters */
1010   _iodbcdm_pool_copy_conn(cp_pdbc, pdbc);
1011   pdbc->cp_pdbc = NULL;
1012 
1013   /* free all statement handle(s) on connection in pool */
1014   while (cp_pdbc->hstmt != NULL)
1015     _iodbcdm_dropstmt (cp_pdbc->hstmt);
1016 
1017   /* set expiration time and other parameters for connection in pool */
1018   cp_pdbc->cp_pdbc = NULL;
1019   if (cp_pdbc->cp_retry_wait == 0)
1020     {
1021       /* set new expiry time only if we are not returning the connection
1022 	 to the pool after unsuccessful reconnect attempt */
1023       cp_pdbc->cp_expiry_time = time(NULL) + cp_pdbc->cp_timeout;
1024     }
1025   cp_pdbc->cp_in_use = FALSE;
1026 
1027   DPRINTF ((stderr, "DEBUG: connection %p put back to the pool (cp_pdbc %p, cp_timeout %d)\n",
1028       hdbc, cp_pdbc, cp_pdbc->cp_timeout));
1029   return 0;
1030 }
1031 #endif /* (ODBCVER >= 0x300) */
1032 
1033 
1034 /* - Load driver share library( or increase its reference count
1035  *   if it has already been loaded by another active connection)
1036  * - Call driver's SQLAllocEnv() (for the first reference only)
1037  * - Call driver's SQLAllocConnect()
1038  * - Call driver's SQLSetConnectOption() (set login time out)
1039  * - Increase the bookkeeping reference count
1040  */
1041 SQLRETURN
_iodbcdm_driverload(char * dsn,char * drv,HDBC hdbc,SWORD thread_safe,SWORD unload_safe,IODBC_CHARSET iodbcinst_drv_cp,UCHAR waMode)1042 _iodbcdm_driverload (
1043     char * dsn,
1044     char * drv,
1045     HDBC hdbc,
1046     SWORD thread_safe,
1047     SWORD unload_safe,
1048     IODBC_CHARSET iodbcinst_drv_cp,
1049     UCHAR waMode)
1050 {
1051   CONN (pdbc, hdbc);
1052   ENVR (penv, NULL);
1053   GENV (genv, NULL);
1054   HDLL hdll = SQL_NULL_HDLL;
1055   HPROC hproc;
1056   SQLRETURN retcode = SQL_SUCCESS;
1057   sqlstcode_t sqlstat = en_00000;
1058   char buf[1024];
1059   char path_tmp[1024];
1060   char *path = drv;
1061   char cp_probe[1024] = {""};
1062   int cp_timeout = 0;
1063   void *pfaux;
1064   int driver_unicode_cp = -1;
1065   SQLINTEGER wchar_id;
1066 
1067   if (drv == NULL || ((char*)drv)[0] == '\0')
1068     {
1069       PUSHSQLERR (pdbc->herr, en_IM002);
1070       return SQL_ERROR;
1071     }
1072 
1073   if (!IS_VALID_HDBC (pdbc) || pdbc->genv == SQL_NULL_HENV)
1074     {
1075       return SQL_INVALID_HANDLE;
1076     }
1077 
1078   /*
1079    *  If drv does not start with / or ., we may have a symbolic driver name
1080    */
1081   if (!(drv[0] == '/' || drv[0] == '.'))
1082     {
1083       char *tmp_drv = NULL;
1084 
1085       /*
1086        *  Remove curly braces
1087        */
1088       if (drv[0] == '{')
1089 	{
1090 	  tmp_drv = strdup (drv);
1091 	  if (tmp_drv[strlen (drv) - 1] == '}')
1092 	    tmp_drv[strlen (drv) - 1] = '\0';
1093 	  drv = &tmp_drv[1];
1094 	}
1095 
1096       /*
1097        *  Hopefully the driver was registered under that name in the
1098        *  odbcinst.ini file
1099        */
1100       if (SQLGetPrivateProfileString ((char *) drv, "Driver", "",
1101 	      path_tmp, sizeof (path_tmp), "odbcinst.ini") && path_tmp[0])
1102 	path = path_tmp;
1103 
1104       /*
1105        *  Get CPTimeout value
1106        */
1107       SQLSetConfigMode (ODBC_BOTH_DSN);
1108       if (SQLGetPrivateProfileString (drv, "CPTimeout", "",
1109 	    buf, sizeof(buf), "odbcinst.ini") && buf[0])
1110         cp_timeout = atoi(buf);
1111 
1112       /*
1113        *  Get CPProbe value
1114        */
1115       SQLGetPrivateProfileString (drv, "CPProbe", "",
1116    	    cp_probe, sizeof(cp_probe), "odbcinst.ini");
1117 
1118       if (SQLGetPrivateProfileString ((char *) drv,
1119           "DriverUnicodeType", "3", buf, sizeof (buf), "odbcinst.ini"))
1120         {
1121           if (STRCASEEQ (buf, "1") || STRCASEEQ (buf, "utf16") || STRCASEEQ (buf, "ucs2"))
1122             iodbcinst_drv_cp = CP_UTF16;
1123           else if (STRCASEEQ (buf, "2") || STRCASEEQ (buf, "utf8"))
1124             iodbcinst_drv_cp = CP_UTF8;
1125           else
1126             iodbcinst_drv_cp = CP_UCS4;
1127 
1128           DPRINTF ((stderr,
1129             "DEBUG: _iodbcdm_driverload-0(odbcinst.ini) DriverUnicodeType=%s\n",
1130               iodbcinst_drv_cp==CP_UCS4?"UCS4":(iodbcinst_drv_cp==CP_UTF16?"UTF16":"UTF8")));
1131         }
1132 
1133       if (tmp_drv)
1134 	free (tmp_drv);
1135     }
1136   else if (dsn != NULL && *dsn != '\0')
1137     {
1138       char tmp_drv[1024] = {""};
1139 
1140       SQLSetConfigMode (ODBC_BOTH_DSN);
1141       if (SQLGetPrivateProfileString ("ODBC Data Sources", dsn, "",
1142 	    tmp_drv, sizeof(tmp_drv), NULL) && tmp_drv[0])
1143 	{
1144           /*
1145            *  Get CPTimeout value
1146            */
1147           if (SQLGetPrivateProfileString (tmp_drv, "CPTimeout", "",
1148 	        buf, sizeof(buf), "odbcinst.ini") && buf[0])
1149             cp_timeout = atoi(buf);
1150 
1151           /*
1152            *  Get CPProbe value
1153            */
1154           SQLGetPrivateProfileString (tmp_drv, "CPProbe", "",
1155   	      cp_probe, sizeof(cp_probe), "odbcinst.ini");
1156 
1157           if (SQLGetPrivateProfileString ((char *) tmp_drv,
1158               "DriverUnicodeType", "3", buf, sizeof (buf), "odbcinst.ini"))
1159             {
1160               if (STRCASEEQ (buf, "1") || STRCASEEQ (buf, "utf16") || STRCASEEQ (buf, "ucs2"))
1161                 iodbcinst_drv_cp = CP_UTF16;
1162               else if (STRCASEEQ (buf, "2") || STRCASEEQ (buf, "utf8"))
1163                 iodbcinst_drv_cp = CP_UTF8;
1164               else
1165                 iodbcinst_drv_cp = CP_UCS4;
1166 
1167               DPRINTF ((stderr,
1168                 "DEBUG: _iodbcdm_driverload-1(odbcinst.ini) DriverUnicodeType=%s\n",
1169                   iodbcinst_drv_cp==CP_UCS4?"UCS4":(iodbcinst_drv_cp==CP_UTF16?"UTF16":"UTF8")));
1170             }
1171   	}
1172     }
1173 
1174   genv = (GENV_t *) pdbc->genv;
1175 
1176   /* This will either load the driver dll or increase its reference count */
1177   hdll = _iodbcdm_dllopen ((char *) path);
1178 
1179   if (hdll == SQL_NULL_HDLL)
1180     {
1181       PUSHSYSERR (pdbc->herr, _iodbcdm_dllerror ());
1182       PUSHSQLERR (pdbc->herr, en_IM003);
1183       return SQL_ERROR;
1184     }
1185 
1186   /* Set flag if it is safe to unload the driver after use */
1187   if (unload_safe)
1188     _iodbcdm_safe_unload (hdll);
1189 
1190   penv = (ENV_t *) (pdbc->henv);
1191 
1192   if (penv != NULL)
1193     {
1194       if (penv->hdll != hdll)
1195 	{
1196 	  _iodbcdm_driverunload (hdbc, 3);
1197 	  penv->hdll = hdll;
1198 	}
1199       else
1200 	{
1201 	  /*
1202 	   * this will not unload the driver but only decrease its internal
1203 	   * reference count
1204 	   */
1205 	  _iodbcdm_dllclose (hdll);
1206 	}
1207     }
1208 
1209   if (penv == NULL)
1210     {
1211       /*
1212        * find out whether this dll has already been loaded on another
1213        * connection
1214        */
1215       for (penv = (ENV_t *) genv->henv;
1216 	  penv != NULL;
1217 	  penv = (ENV_t *) penv->next)
1218 	{
1219 	  if (penv->hdll == hdll)
1220 	    {
1221 	      /*
1222 	       * this will not unload the driver but only decrease its internal
1223 	       * reference count
1224 	       */
1225 	      _iodbcdm_dllclose (hdll);
1226 	      break;
1227 	    }
1228 	}
1229 
1230       if (penv == NULL)
1231 	/* no connection attaching with this dll */
1232 	{
1233 	  int i;
1234 
1235 	  /* create a new dll env instance */
1236 	  penv = (ENV_t *) MEM_ALLOC (sizeof (ENV_t));
1237 
1238 	  if (penv == NULL)
1239 	    {
1240 	      _iodbcdm_dllclose (hdll);
1241 
1242 	      PUSHSQLERR (pdbc->herr, en_S1001);
1243 
1244 	      return SQL_ERROR;
1245 	    }
1246 
1247 	  penv->conv.dm_cp    = genv->conv.dm_cp;
1248 	  penv->conv.drv_cp   = iodbcinst_drv_cp;
1249 	  /*
1250 	   *  Initialize array of ODBC functions
1251 	   */
1252 	  for (i = 0; i < __LAST_API_FUNCTION__; i++)
1253 	    {
1254 #if 1
1255 	      (penv->dllproc_tab)[i] = SQL_NULL_HPROC;
1256 #else
1257 	      (penv->dllproc_tab)[i] = _iodbcdm_getproc(pdbc, i);
1258 #endif
1259 	    }
1260 
1261 	  pdbc->henv = penv;
1262 	  pdbc->conv = penv->conv;
1263 	  penv->hdll = hdll;
1264 
1265           /*
1266            *  If the driver appears not to be thread safe, use a
1267            *  driver mutex to serialize all calls to this driver
1268            */
1269           penv->thread_safe = thread_safe;
1270           if (!penv->thread_safe)
1271             MUTEX_INIT (penv->drv_lock);
1272 
1273           penv->unicode_driver = 0;
1274           /*
1275            *  If the driver is Unicode
1276            */
1277           pfaux = _iodbcdm_getproc (pdbc, en_ConnectW);
1278           if ((pfaux) && (pfaux != (void *)SQLConnectW))
1279             penv->unicode_driver = 1;
1280 
1281 	  /* call driver's SQLAllocHandle() or SQLAllocEnv() */
1282 
1283 #if (ODBCVER >= 0x0300)
1284 	  hproc = _iodbcdm_getproc (pdbc, en_AllocHandle);
1285 
1286 	  if (hproc)
1287 	    {
1288 	      CALL_DRIVER (hdbc, genv, retcode, hproc,
1289 		  (SQL_HANDLE_ENV, SQL_NULL_HANDLE, &(penv->dhenv)));
1290 	      if (SQL_SUCCEEDED (retcode))
1291 		{
1292 		  /*
1293 		   * This appears to be an ODBC3 driver
1294 		   *
1295 		   * Try to set the app's requested version
1296 		   */
1297 		  SQLRETURN save_retcode = retcode;
1298 
1299 		  penv->dodbc_ver = SQL_OV_ODBC2;
1300 		  hproc = _iodbcdm_getproc (pdbc, en_SetEnvAttr);
1301 		  if (hproc != SQL_NULL_HPROC)
1302 		    {
1303 		      CALL_DRIVER (hdbc, genv, retcode, hproc,
1304 			  (penv->dhenv, SQL_ATTR_ODBC_VERSION, genv->odbc_ver,
1305 			  0));
1306 		      if (retcode == SQL_SUCCESS)
1307 			penv->dodbc_ver = SQL_OV_ODBC3;
1308 		    }
1309 
1310 		  hproc = _iodbcdm_getproc (pdbc, en_GetEnvAttr);
1311 		  if (hproc != SQL_NULL_HPROC)
1312                     {
1313                       SQLINTEGER val, len;
1314 
1315                       val = -1;
1316                       CALL_DRIVER (hdbc, penv, retcode, hproc,
1317 			(penv->dhenv, SQL_ATTR_DRIVER_UNICODE_TYPE, &val, 0, 0));
1318                       if (retcode == SQL_SUCCESS && val !=-1)
1319                         {
1320                           DPRINTF ((stderr,
1321                            "DEBUG: _iodbcdm_driverload(ODBC Driver return=%d)\n", val));
1322 
1323                           if (val == SQL_DM_CP_UCS4 || val == SQL_DM_CP_UTF16 || val == SQL_DM_CP_UTF8)
1324                             {
1325                               switch(val)
1326                                 {
1327                                 case SQL_DM_CP_UTF16:
1328                                   penv->conv.drv_cp = CP_UTF16;
1329                                   pdbc->conv.drv_cp = CP_UTF16;
1330                                   driver_unicode_cp = CP_UTF16;
1331                                   break;
1332                                 case SQL_DM_CP_UTF8:
1333                                   penv->conv.drv_cp = CP_UTF8;
1334                                   pdbc->conv.drv_cp = CP_UTF8;
1335                                   driver_unicode_cp = CP_UTF8;
1336                                   break;
1337                                 default:
1338                                 case SQL_DM_CP_UCS4:
1339                                   penv->conv.drv_cp = CP_UCS4;
1340                                   pdbc->conv.drv_cp = CP_UCS4;
1341                                   driver_unicode_cp = CP_UCS4;
1342                                   break;
1343                                 }
1344                               DPRINTF ((stderr,
1345                                "DEBUG: _iodbcdm_driverload(ODBC Driver return DriverUnicodeType=%s)\n",
1346                                 penv->conv.drv_cp==CP_UCS4
1347                                   ?"UCS4"
1348                                   :(penv->conv.drv_cp==CP_UTF16?"UTF16":"UTF8")));
1349                             }
1350                           else
1351                             {
1352                               penv->conv.drv_cp = iodbcinst_drv_cp;
1353                               pdbc->conv.drv_cp = iodbcinst_drv_cp;
1354 
1355                               DPRINTF ((stderr,
1356                                "DEBUG: _iodbcdm_driverload(ODBC Driver use DriverUnicodeType=UCS4 (default))\n"));
1357                             }
1358                         }
1359                     }
1360 
1361 		  retcode = save_retcode;
1362 		}
1363 	    }
1364 	  else			/* try driver's SQLAllocEnv() */
1365 #endif
1366 	    {
1367 	      hproc = _iodbcdm_getproc (pdbc, en_AllocEnv);
1368 
1369 	      if (hproc == SQL_NULL_HPROC)
1370 		{
1371 		  sqlstat = en_IM004;
1372 		}
1373 	      else
1374 		{
1375 #if (ODBCVER >= 0x0300)
1376 		  penv->dodbc_ver = SQL_OV_ODBC2;
1377 #endif
1378 		  CALL_DRIVER (hdbc, genv, retcode, hproc, (&(penv->dhenv)));
1379 		}
1380 	    }
1381 
1382 	  if (retcode == SQL_ERROR)
1383 	    {
1384 	      sqlstat = en_IM004;
1385 	    }
1386 
1387 	  if (sqlstat != en_00000)
1388 	    {
1389 	      _iodbcdm_dllclose (hdll);
1390 	      PUSHSQLERR (pdbc->herr, en_IM004);
1391 
1392 	      /* free internal env */
1393 	      MEM_FREE (penv);
1394 	      pdbc->henv = NULL;
1395 
1396 	      return SQL_ERROR;
1397 	    }
1398 
1399           if (driver_unicode_cp == -1
1400               && penv->unicode_driver
1401               && dsn != NULL && *dsn != '\0')
1402             {
1403               SQLSetConfigMode (ODBC_BOTH_DSN);
1404 
1405               if ( SQLGetPrivateProfileString ((char *) dsn,
1406                     "DriverUnicodeType", "", buf, sizeof(buf), "odbc.ini"))
1407                 {
1408                   if (STRCASEEQ (buf, "1") || STRCASEEQ (buf, "utf16"))
1409                     {
1410                       penv->conv.drv_cp = CP_UTF16;
1411                       pdbc->conv.drv_cp = CP_UTF16;
1412                     }
1413                   else if (STRCASEEQ (buf, "2") || STRCASEEQ (buf, "utf8"))
1414                     {
1415                       penv->conv.drv_cp = CP_UTF8;
1416                       pdbc->conv.drv_cp = CP_UTF8;
1417                     }
1418                   else if (STRCASEEQ (buf, "3") || STRCASEEQ (buf, "ucs4"))
1419                     {
1420                       penv->conv.drv_cp = CP_UCS4;
1421                       pdbc->conv.drv_cp = CP_UCS4;
1422                     }
1423 
1424                   DPRINTF ((stderr,
1425                    "DEBUG: _iodbcdm_driverload(DSN attribute) DriverUnicodeType=%s\n",
1426                     penv->conv.drv_cp==CP_UCS4
1427                       ?"UCS4":(penv->conv.drv_cp==CP_UTF16?"UTF16":"UTF8")));
1428 
1429                 }
1430             }
1431 
1432 	  /* insert into dll env list */
1433 	  penv->next = (ENV_t *) genv->henv;
1434 	  genv->henv = penv;
1435 
1436 	  /* initiate this new env entry */
1437 	  penv->refcount = 0;	/* we will increase it after
1438 				 * driver's SQLAllocConnect()
1439 				 * success
1440 				 */
1441 	}
1442       else /* penv != NULL */
1443         {
1444           pdbc->conv.drv_cp = penv->conv.drv_cp;
1445 #if (ODBCVER >= 0x0300)
1446 	  hproc = _iodbcdm_getproc (pdbc, en_GetEnvAttr);
1447 	  if (hproc != SQL_NULL_HPROC)
1448             {
1449               SQLINTEGER val;
1450 
1451               val = -1;
1452               CALL_DRIVER (hdbc, penv, retcode, hproc,
1453 	  	    (penv->dhenv, SQL_ATTR_DRIVER_UNICODE_TYPE, &val, 0, 0));
1454               if (retcode == SQL_SUCCESS && val !=-1)
1455                 {
1456                   if (val == SQL_DM_CP_UCS4 || val == SQL_DM_CP_UTF16 || val == SQL_DM_CP_UTF8)
1457                     {
1458                       switch(val)
1459                         {
1460                         case SQL_DM_CP_UTF16:
1461                           driver_unicode_cp = CP_UTF16;
1462                           break;
1463                         case SQL_DM_CP_UTF8:
1464                           driver_unicode_cp = CP_UTF8;
1465                           break;
1466                         default:
1467                         case SQL_DM_CP_UCS4:
1468                           driver_unicode_cp = CP_UCS4;
1469                           break;
1470                         }
1471                     }
1472                 }
1473             }
1474 #endif
1475         }
1476 
1477       pdbc->henv = penv;
1478 
1479       if (pdbc->dhdbc == SQL_NULL_HDBC)
1480 	{
1481 
1482 #if (ODBCVER >= 0x0300)
1483 	  hproc = _iodbcdm_getproc (pdbc, en_AllocHandle);
1484 
1485 	  if (hproc)
1486 	    {
1487 	      CALL_DRIVER (hdbc, genv, retcode, hproc,
1488 		  (SQL_HANDLE_DBC, penv->dhenv, &(pdbc->dhdbc)));
1489 	    }
1490 	  else
1491 #endif
1492 
1493 	    {
1494 	      hproc = _iodbcdm_getproc (pdbc, en_AllocConnect);
1495 
1496 	      if (hproc == SQL_NULL_HPROC)
1497 		{
1498 		  sqlstat = en_IM005;
1499 		}
1500 	      else
1501 		{
1502 		  CALL_DRIVER (hdbc, genv, retcode, hproc,
1503 		      (penv->dhenv, &(pdbc->dhdbc)));
1504 		}
1505 	    }
1506 
1507 	  if (retcode == SQL_ERROR)
1508 	    {
1509 	      sqlstat = en_IM005;
1510 	    }
1511 
1512 	  if (sqlstat != en_00000)
1513 	    {
1514 	      _iodbcdm_driverunload (hdbc, 3);
1515 
1516 	      pdbc->dhdbc = SQL_NULL_HDBC;
1517 	      PUSHSQLERR (pdbc->herr, en_IM005);
1518 
1519 	      return SQL_ERROR;
1520 	    }
1521 	}
1522 
1523       pdbc->henv = penv;
1524       penv->refcount++;		/* bookkeeping reference count on this driver */
1525     }
1526   else  /*penv != NULL */
1527     {
1528       pdbc->conv.drv_cp = penv->conv.drv_cp;
1529 #if (ODBCVER >= 0x0300)
1530       hproc = _iodbcdm_getproc (pdbc, en_GetEnvAttr);
1531       if (hproc != SQL_NULL_HPROC)
1532         {
1533           SQLINTEGER val;
1534 
1535           val = -1;
1536           CALL_DRIVER (hdbc, penv, retcode, hproc,
1537               (penv->dhenv, SQL_ATTR_DRIVER_UNICODE_TYPE, &val, 0, 0));
1538           if (retcode == SQL_SUCCESS && val !=-1)
1539             {
1540               if (val == SQL_DM_CP_UCS4 || val == SQL_DM_CP_UTF16 || val == SQL_DM_CP_UTF8)
1541                 {
1542                   switch(val)
1543                     {
1544                     case SQL_DM_CP_UTF16:
1545                       driver_unicode_cp = CP_UTF16;
1546                       break;
1547                     case SQL_DM_CP_UTF8:
1548                       driver_unicode_cp = CP_UTF8;
1549                       break;
1550                     default:
1551                     case SQL_DM_CP_UCS4:
1552                       driver_unicode_cp = CP_UCS4;
1553                       break;
1554                     }
1555                 }
1556             }
1557         }
1558 #endif
1559     }
1560 
1561   /* driver's login timeout option must been set before
1562    * its SQLConnect() call */
1563   if (pdbc->login_timeout != 0UL)
1564     {
1565       retcode = _iodbcdm_SetConnectOption_init (hdbc, SQL_LOGIN_TIMEOUT,
1566 	pdbc->login_timeout, waMode);
1567 
1568       if (retcode == SQL_ERROR)
1569         {
1570           PUSHSQLERR (pdbc->herr, en_IM006);
1571           return SQL_SUCCESS_WITH_INFO;
1572         }
1573     }
1574 
1575   /*
1576    *  Now set the driver specific options we saved earlier
1577    */
1578   if (pdbc->drvopt != NULL)
1579     {
1580       DRVOPT *popt;
1581 
1582       for (popt = pdbc->drvopt; popt != NULL; popt = popt->next)
1583         {
1584           retcode = _iodbcdm_SetConnectOption_init (hdbc, popt->Option,
1585 	    popt->Param, popt->waMode);
1586 
1587           if (retcode == SQL_ERROR)
1588             {
1589 	      PUSHSQLERR (pdbc->herr, en_IM006);
1590 	      return SQL_SUCCESS_WITH_INFO;
1591 	    }
1592         }
1593     }
1594 
1595 
1596     wchar_id = penv->conv.dm_cp;
1597 
1598     retcode = _iodbcdm_SetConnectAttr_init (hdbc, SQL_ATTR_APP_WCHAR_TYPE, wchar_id);
1599 
1600     DPRINTF ((stderr, "DEBUG: _iodbcdm_driverload(set ODBC Driver WCHAR_TYPE=%d) retcode=%d\n", wchar_id, retcode));
1601 
1602     if (retcode == SQL_SUCCESS)
1603       {
1604         penv->conv.drv_cp = wchar_id;
1605         pdbc->conv.drv_cp = wchar_id;
1606 
1607         DPRINTF ((stderr,
1608             "DEBUG: _iodbcdm_driverload(set ODBC Driver WCHAR_TYPE=%d) %s\n",
1609                penv->conv.drv_cp,
1610                penv->conv.drv_cp==CP_UCS4
1611                           ?"UCS4"
1612                           :(penv->conv.drv_cp==CP_UTF16?"UTF16":"UTF8")));
1613       }
1614     else if (driver_unicode_cp != -1)
1615       {
1616         wchar_id = driver_unicode_cp;
1617 
1618         retcode = _iodbcdm_SetConnectAttr_init (hdbc, SQL_ATTR_APP_WCHAR_TYPE, wchar_id);
1619 
1620         DPRINTF ((stderr, "DEBUG: _iodbcdm_driverload(set ODBC Driver WCHAR_TYPE=%d) retcode=%d\n", wchar_id, retcode));
1621         if (retcode == SQL_SUCCESS)
1622           {
1623             penv->conv.drv_cp = wchar_id;
1624             pdbc->conv.drv_cp = wchar_id;
1625 
1626             DPRINTF ((stderr,
1627                 "DEBUG: _iodbcdm_driverload(set ODBC Driver WCHAR_TYPE=%d) %s\n",
1628                    penv->conv.drv_cp,
1629                    penv->conv.drv_cp==CP_UCS4
1630                           ?"UCS4"
1631                           :(penv->conv.drv_cp==CP_UTF16?"UTF16":"UTF8")));
1632           }
1633       }
1634 
1635   pdbc->cp_timeout = cp_timeout;
1636   MEM_FREE (pdbc->cp_probe);
1637   pdbc->cp_probe = strdup (cp_probe);
1638 
1639   return SQL_SUCCESS;
1640 }
1641 
1642 
1643 /* - Call driver's SQLFreeConnect()
1644  * - Call driver's SQLFreeEnv() ( for the last reference only)
1645  * - Unload the share library( or decrease its reference
1646  *   count if it is not the last reference )
1647  * - decrease bookkeeping reference count
1648  * - state transition to allocated
1649  */
1650 SQLRETURN
_iodbcdm_driverunload(HDBC hdbc,int ver)1651 _iodbcdm_driverunload (HDBC hdbc, int ver)
1652 {
1653   CONN (pdbc, hdbc);
1654   ENVR (penv, pdbc->henv);
1655   GENV (genv, pdbc->genv);
1656   ENV_t *tpenv;
1657   HPROC hproc2, hproc3;
1658   SQLRETURN retcode = SQL_SUCCESS;
1659 
1660   if (!IS_VALID_HDBC (pdbc))
1661     {
1662       return SQL_INVALID_HANDLE;
1663     }
1664 
1665   if (penv == NULL || penv->hdll == SQL_NULL_HDLL ||
1666       pdbc->dhdbc == SQL_NULL_HDBC)
1667     {
1668       return SQL_SUCCESS;
1669     }
1670 
1671   /*
1672    *  When calling from an ODBC 2.x application, we favor the ODBC 2.x call
1673    *  in the driver if the driver implements both
1674    */
1675   hproc2 = _iodbcdm_getproc (pdbc, en_FreeConnect);
1676 #if (ODBCVER >= 0x0300)
1677   hproc3 = _iodbcdm_getproc (pdbc, en_FreeHandle);
1678 
1679   if (ver == 3 && hproc2 != SQL_NULL_HPROC && hproc3 != SQL_NULL_HPROC)
1680     hproc2 = SQL_NULL_HPROC;
1681 #else
1682   hproc3 = SQL_NULL_HPROC;
1683 #endif
1684 
1685   if (hproc2 != SQL_NULL_HPROC)
1686     {
1687       CALL_DRIVER (hdbc, pdbc, retcode, hproc2, (pdbc->dhdbc));
1688 
1689       pdbc->dhdbc = SQL_NULL_HDBC;
1690     }
1691 #if (ODBCVER >= 0x0300)
1692   else if (hproc3 != SQL_NULL_HPROC)
1693     {
1694       CALL_DRIVER (hdbc, pdbc, retcode, hproc3,
1695 	  (SQL_HANDLE_DBC, pdbc->dhdbc));
1696     }
1697 #endif
1698 
1699   penv->refcount--;
1700 
1701   if (!penv->refcount)
1702     /* no other connections still attaching with this driver */
1703     {
1704       /*
1705        *  When calling from an ODBC 2.x application, we favor the ODBC 2.x call
1706        *  in the driver if the driver implements both
1707        */
1708       hproc2 = _iodbcdm_getproc (pdbc, en_FreeEnv);
1709 #if (ODBCVER >= 0x0300)
1710       hproc3 = _iodbcdm_getproc (pdbc, en_FreeHandle);
1711 
1712       if (ver == 3 && hproc2 != SQL_NULL_HPROC && hproc3 != SQL_NULL_HPROC)
1713 	hproc2 = SQL_NULL_HPROC;
1714 #else
1715       hproc3 = SQL_NULL_HPROC;
1716 #endif
1717 
1718       if (hproc2 != SQL_NULL_HPROC)
1719 	{
1720 	  CALL_DRIVER (hdbc, genv, retcode, hproc2, (penv->dhenv));
1721 
1722 	  penv->dhenv = SQL_NULL_HENV;
1723 	}
1724 #if (ODBCVER >= 0x0300)
1725       else if (hproc3 != SQL_NULL_HPROC)
1726 	{
1727 	  CALL_DRIVER (hdbc, genv, retcode, hproc3,
1728 	      (SQL_HANDLE_ENV, penv->dhenv));
1729 	}
1730 #endif
1731 
1732       _iodbcdm_dllclose (penv->hdll);
1733 
1734       penv->hdll = SQL_NULL_HDLL;
1735 
1736       for (tpenv = (ENV_t *) genv->henv;
1737 	  tpenv != NULL; tpenv = (ENV_t *) tpenv->next)
1738 	{
1739 	  if (tpenv == penv)
1740 	    {
1741 	      genv->henv = penv->next;
1742 	      break;
1743 	    }
1744 
1745 	  if (tpenv->next == penv)
1746 	    {
1747 	      tpenv->next = penv->next;
1748 	      break;
1749 	    }
1750 	}
1751 
1752       /* free internal env */
1753       MEM_FREE (penv);
1754       pdbc->henv = NULL;
1755     }
1756 
1757   /* pdbc->henv = SQL_NULL_HENV; */
1758   pdbc->hstmt = SQL_NULL_HSTMT;
1759   /* pdbc->herr = SQL_NULL_HERR;
1760      -- delay to DM's SQLFreeConnect() */
1761   pdbc->dhdbc = SQL_NULL_HDBC;
1762   pdbc->state = en_dbc_allocated;
1763 
1764   /* set connect options to default values */
1765 	/**********
1766 	pdbc->access_mode	= SQL_MODE_DEFAULT;
1767 	pdbc->autocommit	= SQL_AUTOCOMMIT_DEFAULT;
1768 	pdbc->login_timeout 	= 0UL;
1769 	**********/
1770   pdbc->odbc_cursors = SQL_CUR_DEFAULT;
1771   pdbc->packet_size = 0UL;
1772   pdbc->quiet_mode = (UDWORD) NULL;
1773   pdbc->txn_isolation = SQL_TXN_READ_UNCOMMITTED;
1774 
1775 #if (ODBCVER >= 0x0300)
1776   if (pdbc->cp_probe != NULL)
1777     {
1778       MEM_FREE (pdbc->cp_probe);
1779       pdbc->cp_probe = NULL;
1780     }
1781   if (pdbc->cp_dsn != NULL)
1782     {
1783       MEM_FREE (pdbc->cp_dsn);
1784       pdbc->cp_dsn = NULL;
1785     }
1786   if (pdbc->cp_uid != NULL)
1787     {
1788       MEM_FREE (pdbc->cp_uid);
1789       pdbc->cp_uid = NULL;
1790     }
1791   if (pdbc->cp_pwd != NULL)
1792     {
1793       MEM_FREE (pdbc->cp_pwd);
1794       pdbc->cp_pwd = NULL;
1795     }
1796   if (pdbc->cp_connstr != NULL)
1797     {
1798       MEM_FREE (pdbc->cp_connstr);
1799       pdbc->cp_connstr = NULL;
1800     }
1801 #endif
1802 
1803   if (pdbc->current_qualifier != NULL)
1804     {
1805       MEM_FREE (pdbc->current_qualifier);
1806       pdbc->current_qualifier = NULL;
1807     }
1808 
1809   return SQL_SUCCESS;
1810 }
1811 
1812 
1813 static SQLRETURN
_iodbcdm_dbcdelayset(HDBC hdbc,UCHAR waMode)1814 _iodbcdm_dbcdelayset (HDBC hdbc, UCHAR waMode)
1815 {
1816   CONN (pdbc, hdbc);
1817   SQLRETURN retcode = SQL_SUCCESS;
1818   SQLRETURN ret;
1819 
1820   if (pdbc->access_mode != SQL_MODE_DEFAULT)
1821     {
1822       ret = _iodbcdm_SetConnectOption_init (hdbc, SQL_ACCESS_MODE,
1823 	      pdbc->access_mode, waMode);
1824 
1825       retcode |= ret;
1826     }
1827 
1828   if (pdbc->autocommit != SQL_AUTOCOMMIT_DEFAULT)
1829     {
1830       ret = _iodbcdm_SetConnectOption_init (hdbc, SQL_AUTOCOMMIT,
1831 	      pdbc->autocommit, waMode);
1832 
1833       retcode |= ret;
1834     }
1835 
1836   if (pdbc->current_qualifier != NULL)
1837     {
1838       ret = _iodbcdm_SetConnectOption_init (hdbc, SQL_CURRENT_QUALIFIER,
1839 	      (SQLULEN) pdbc->current_qualifier,
1840 	      pdbc->current_qualifier_WA);
1841 
1842       retcode |= ret;
1843     }
1844 
1845   if (pdbc->packet_size != 0UL)
1846     {
1847       ret = _iodbcdm_SetConnectOption_init (hdbc, SQL_PACKET_SIZE,
1848 	      pdbc->packet_size, waMode);
1849 
1850       retcode |= ret;
1851     }
1852 
1853   if (pdbc->quiet_mode != (UDWORD) NULL)
1854     {
1855       ret = _iodbcdm_SetConnectOption_init (hdbc, SQL_QUIET_MODE,
1856 	      pdbc->quiet_mode, waMode);
1857 
1858       retcode |= ret;
1859     }
1860 
1861   if (pdbc->txn_isolation != SQL_TXN_READ_UNCOMMITTED)
1862     {
1863       ret = _iodbcdm_SetConnectOption_init (hdbc, SQL_TXN_ISOLATION,
1864 	      pdbc->txn_isolation, waMode);
1865 
1866       retcode |= ret;
1867     }
1868 
1869   /* check error code for driver's SQLSetConnectOption() call */
1870   if (!SQL_SUCCEEDED (retcode))
1871     {
1872       PUSHSQLERR (pdbc->herr, en_IM006);
1873       retcode = SQL_ERROR;
1874     }
1875 
1876 
1877   /* get cursor behavior on transaction commit or rollback */
1878   ret = _iodbcdm_getInfo_init (hdbc, SQL_CURSOR_COMMIT_BEHAVIOR,
1879 	    (PTR) & (pdbc->cb_commit),
1880 	    sizeof (pdbc->cb_commit),
1881 	    NULL, waMode);
1882   retcode |= ret;
1883 
1884   ret = _iodbcdm_getInfo_init (hdbc, SQL_CURSOR_ROLLBACK_BEHAVIOR,
1885 	    (PTR) & (pdbc->cb_rollback),
1886 	    sizeof (pdbc->cb_rollback),
1887 	    NULL, waMode);
1888   retcode |= ret;
1889 
1890   if (retcode != SQL_SUCCESS  && retcode != SQL_SUCCESS_WITH_INFO)
1891     {
1892       return SQL_ERROR;
1893     }
1894 
1895   return retcode;
1896 }
1897 
1898 
1899 static SQLRETURN
_iodbcdm_con_settracing(HDBC hdbc,SQLCHAR * dsn,int dsnlen,UCHAR waMode)1900 _iodbcdm_con_settracing (HDBC hdbc, SQLCHAR *dsn, int dsnlen, UCHAR waMode)
1901 {
1902   SQLUINTEGER trace = SQL_OPT_TRACE_OFF;
1903   char buf[1024];
1904 
1905   /* Unused */
1906   hdbc=hdbc;
1907   dsnlen=dsnlen;
1908   waMode = waMode;
1909 
1910   /* Get the TraceFile keyword value from the ODBC section */
1911   SQLSetConfigMode (ODBC_BOTH_DSN);
1912   if ((SQLGetPrivateProfileString ((char *) dsn, "TraceFile", "",
1913 	buf, sizeof (buf), "odbc.ini") == 0 || !buf[0]))
1914     STRCPY (buf, SQL_OPT_TRACE_FILE_DEFAULT);
1915 
1916   trace_set_filename (buf);	/* UTF-8 */
1917 
1918   /* Get the Trace keyword value from the ODBC section */
1919   SQLSetConfigMode (ODBC_BOTH_DSN);
1920   if (SQLGetPrivateProfileString ((char *) dsn, "Trace", "",
1921 	buf, sizeof (buf), "odbc.ini")
1922       && (STRCASEEQ (buf, "on") || STRCASEEQ (buf, "yes")
1923 	  || STRCASEEQ (buf, "1")))
1924     {
1925       trace = SQL_OPT_TRACE_ON;
1926     }
1927 
1928   /* Set the trace flag now */
1929   if (trace == SQL_OPT_TRACE_ON)
1930     trace_start ();
1931 
1932   return SQL_SUCCESS;
1933 }
1934 
1935 
1936 #define CATBUF(buf, str, buf_sz)					\
1937   do {									\
1938     if (_iodbcdm_strlcat (buf, str, buf_sz) >= buf_sz)			\
1939       return -1;							\
1940   } while (0)
1941 
1942 
1943 /*
1944  * Merge the contents of .dsn file into config
1945  */
1946 static int
_iodbcdm_cfg_merge_filedsn(PCONFIG pconfig,const char * filedsn,char * buf,size_t buf_sz,int wide,DM_CONV * conv)1947 _iodbcdm_cfg_merge_filedsn (PCONFIG pconfig, const char *filedsn,
1948 			    char *buf, size_t buf_sz, int wide,
1949 			    DM_CONV *conv)
1950 {
1951   BOOL override;	/* TRUE if params from conn str
1952 			   override params from .dsn file */
1953   WORD len;
1954   char *p, *p_next;
1955   char entries[1024];
1956   char value[1024];
1957   char drv_value[1024] = {"\0"};
1958   char *tmp = NULL;
1959   int rc = 0;
1960 
1961   /* identify params precedence */
1962   if (SQLReadFileDSN (filedsn, "ODBC", "DRIVER", value, sizeof (value), &len) &&
1963       len > 0)
1964     {
1965       /* if DRIVER is the same, then conn str params have precedence */
1966       if (_iodbcdm_cfg_find (pconfig, "ODBC", "DRIVER") == 0 &&
1967 	  !strcasecmp (value, pconfig->value))
1968         override = TRUE;
1969       else
1970         override = FALSE;
1971     }
1972   else
1973     override = TRUE;
1974 
1975   /* get list of entries in .dsn file */
1976   if (!SQLReadFileDSN (filedsn, "ODBC", NULL,
1977 		       entries, sizeof (entries), &len))
1978     return -1;
1979 
1980   /* ignore DSN from connection string */
1981   _iodbcdm_cfg_write (pconfig, "ODBC", "DSN", NULL);
1982 
1983   /* add params from the .dsn file */
1984   for (p = entries; *p != '\0'; p = p_next)
1985     {
1986       /* get next entry */
1987       p_next = strchr (p, ';');
1988       if (p_next)
1989         *p_next++ = '\0';
1990 
1991       if ((override || !strcasecmp (p, "DRIVER")) &&
1992 	  _iodbcdm_cfg_find (pconfig, "ODBC", p) == 0)
1993         {
1994 	  /* skip param because it is specified in connection string */
1995           continue;
1996         }
1997 
1998       if (!SQLReadFileDSN (filedsn, "ODBC", p, value, sizeof(value), &len))
1999         return -1;
2000       _iodbcdm_cfg_write (pconfig, "ODBC", p, value);
2001     }
2002 
2003   /* remove FILEDSN from new config */
2004   _iodbcdm_cfg_write (pconfig, "ODBC", "FILEDSN", NULL);
2005 
2006   if (_iodbcdm_cfg_find (pconfig, "ODBC", "DRIVER") == 0)
2007     strncpy(drv_value, pconfig->value, sizeof(drv_value));
2008 
2009   /* remove DRIVER from new config */
2010   _iodbcdm_cfg_write (pconfig, "ODBC", "DRIVER", NULL);
2011 
2012   /* construct new connection string */
2013   if ((rc =_iodbcdm_cfg_to_string (pconfig, "ODBC", buf, buf_sz)) == -1)
2014     goto done;
2015 
2016   tmp = strdup(buf);
2017   strncpy(buf, "DRIVER=", buf_sz);
2018   CATBUF(buf, drv_value, buf_sz);
2019   CATBUF(buf, ";", buf_sz);
2020   CATBUF(buf, tmp, buf_sz);
2021   MEM_FREE(tmp);
2022 
2023   if (wide)
2024     {
2025       SQLWCHAR *_in = DM_U8toW (conv, (SQLCHAR *)buf, SQL_NTS);
2026       if (_in == NULL)
2027         {
2028           rc = -1;
2029           goto done;
2030         }
2031       DM_WCSNCPY (conv, buf, _in, buf_sz / DM_WCHARSIZE(conv));
2032       MEM_FREE (_in);
2033     }
2034 
2035   rc = 0;
2036 
2037 done:
2038   if (drv_value[0])
2039     _iodbcdm_cfg_write (pconfig, "ODBC", "DRIVER", drv_value);
2040 
2041   return rc;
2042 }
2043 
2044 
2045 /*
2046  * Save connection string into the file
2047  */
2048 static int
_iodbcdm_cfg_savefile(const char * savefile,void * conn_str,int wide,DM_CONV * conv)2049 _iodbcdm_cfg_savefile (const char *savefile, void *conn_str, int wide,
2050 	DM_CONV *conv)
2051 {
2052   int ret = 0;
2053   PCONFIG pconfig;
2054   BOOL atsection = FALSE;
2055 
2056   /* parse connection string into pconfig */
2057   if (_iodbcdm_cfg_init_str (&pconfig, conn_str, SQL_NTS, wide, conv) == -1)
2058     return -1;
2059 
2060   /* don't save PWD, FILEDSN and SAVEFILE */
2061   _iodbcdm_cfg_write (pconfig, "ODBC", "PWD", NULL);
2062   _iodbcdm_cfg_write (pconfig, "ODBC", "FILEDSN", NULL);
2063   _iodbcdm_cfg_write (pconfig, "ODBC", "SAVEFILE", NULL);
2064   _iodbcdm_cfg_write (pconfig, "ODBC", "DSN", NULL);
2065 
2066   /* save the file */
2067   SQLWriteFileDSN (savefile, "ODBC", "DSN", NULL);
2068   _iodbcdm_cfg_rewind (pconfig);
2069   while (_iodbcdm_cfg_nextentry (pconfig) == 0)
2070     {
2071       if (atsection)
2072 	{
2073 	  if (_iodbcdm_cfg_section (pconfig))
2074 	    {
2075               /* found next section -- we're done */
2076               break;
2077             }
2078 	  else if (_iodbcdm_cfg_define (pconfig))
2079 	    {
2080               if (!SQLWriteFileDSN (savefile, "ODBC",
2081 				    pconfig->id, pconfig->value))
2082 		{
2083 		  ret = -1;
2084 		  break;
2085 		}
2086 	    }
2087 	}
2088       else if (_iodbcdm_cfg_section (pconfig)
2089 	  && !strcasecmp (pconfig->section, "ODBC"))
2090 	atsection = TRUE;
2091     }
2092 
2093   _iodbcdm_cfg_done (pconfig);
2094   return ret;
2095 }
2096 
2097 
2098 static
2099 SQLRETURN SQL_API
SQLConnect_Internal(SQLHDBC hdbc,SQLPOINTER szDSN,SQLSMALLINT cbDSN,SQLPOINTER szUID,SQLSMALLINT cbUID,SQLPOINTER szAuthStr,SQLSMALLINT cbAuthStr,SQLCHAR waMode)2100 SQLConnect_Internal (SQLHDBC hdbc,
2101     SQLPOINTER szDSN,
2102     SQLSMALLINT cbDSN,
2103     SQLPOINTER szUID,
2104     SQLSMALLINT cbUID,
2105     SQLPOINTER szAuthStr,
2106     SQLSMALLINT cbAuthStr,
2107     SQLCHAR waMode)
2108 {
2109   CONN (pdbc, hdbc);
2110   ENVR (penv, NULL);
2111 #if (ODBCVER >= 0x300)
2112   GENV (genv, NULL);
2113 #endif
2114   SQLRETURN retcode = SQL_SUCCESS;
2115   SQLRETURN setopterr = SQL_SUCCESS;
2116   /* MS SDK Guide specifies driver path can't longer than 255. */
2117   char driver[1024] = { '\0' };
2118   char buf[256];
2119   HPROC hproc = SQL_NULL_HPROC;
2120   SWORD thread_safe;
2121   SWORD unload_safe;
2122   void * _szDSN = NULL;
2123   void * _szUID = NULL;
2124   void * _szAuthStr = NULL;
2125   SQLCHAR *_dsn = (SQLCHAR *) szDSN;
2126   SQLSMALLINT _dsn_len = cbDSN;
2127   CONV_DIRECT conv_direct = CD_NONE;
2128   DM_CONV *conv = NULL;
2129   IODBC_CHARSET drv_cp = CP_DEF;
2130 
2131   /* check arguments */
2132   if ((cbDSN < 0 && cbDSN != SQL_NTS)
2133       || (cbUID < 0 && cbUID != SQL_NTS)
2134       || (cbAuthStr < 0 && cbAuthStr != SQL_NTS)
2135       || (cbDSN > SQL_MAX_DSN_LENGTH))
2136     {
2137       PUSHSQLERR (pdbc->herr, en_S1090);
2138       RETURN (SQL_ERROR);
2139     }
2140 
2141   if (szDSN == NULL || cbDSN == 0)
2142     {
2143       PUSHSQLERR (pdbc->herr, en_IM002);
2144       RETURN (SQL_ERROR);
2145     }
2146 
2147   /* check state */
2148   if (pdbc->state != en_dbc_allocated)
2149     {
2150       PUSHSQLERR (pdbc->herr, en_08002);
2151       RETURN (SQL_ERROR);
2152     }
2153 
2154 
2155   conv = (penv != SQL_NULL_HENV) ? &penv->conv : &((GENV_t *) pdbc->genv)->conv;
2156 
2157   if (waMode == 'W')
2158     {
2159       _szDSN = (void *) DM_WtoU8(conv, szDSN, cbDSN);
2160       _dsn = (SQLCHAR *) _szDSN;
2161       _dsn_len = SQL_NTS;
2162       if (_dsn == NULL)
2163         {
2164           PUSHSQLERR (pdbc->herr, en_S1001);
2165           RETURN (SQL_ERROR);
2166         }
2167     }
2168 
2169   /* Get the config mode */
2170   if (_iodbcdm_con_settracing (pdbc, _dsn, _dsn_len, waMode) == SQL_ERROR)
2171     RETURN (SQL_ERROR);
2172 
2173 #if (ODBCVER >= 0x300)
2174   genv = (GENV_t *) pdbc->genv;
2175 
2176   if (genv->connection_pooling != SQL_CP_OFF)
2177     {
2178       char *_uid = szUID;
2179       char *_pwd = szAuthStr;
2180 
2181       /*
2182        * _dsn is already an UTF8 string so
2183        * need to convert to UTF8 only szUID and szAuthStr
2184        */
2185       if (waMode == 'W')
2186         {
2187           if (szUID != NULL)
2188 	    {
2189               _szUID = (void *) DM_WtoU8(conv, (SQLWCHAR *) szUID, cbUID);
2190 	      if (_szUID == NULL)
2191 	        {
2192 		  PUSHSQLERR (pdbc->herr, en_S1001);
2193 		  RETURN (SQL_ERROR);
2194 	        }
2195 	    }
2196           if (szAuthStr != NULL)
2197 	    {
2198               _szAuthStr = (void *) DM_WtoU8(conv,
2199 	          (SQLWCHAR *) szAuthStr, cbAuthStr);
2200 	      if (_szAuthStr == NULL)
2201 	        {
2202 		  PUSHSQLERR (pdbc->herr, en_S1001);
2203 		  RETURN (SQL_ERROR);
2204 	        }
2205 	    }
2206 	  _uid = _szUID;
2207 	  _pwd = _szAuthStr;
2208         }
2209 
2210       retcode = _iodbcdm_pool_get_conn (pdbc, (char *)_dsn, _uid, _pwd, NULL);
2211       if (SQL_SUCCEEDED (retcode))
2212         {
2213 	  /*
2214 	   * Got connection from the pool
2215 	   */
2216 
2217           /* state transition */
2218           pdbc->state = en_dbc_connected;
2219 
2220           RETURN (retcode);
2221         }
2222 
2223       if (pdbc->cp_pdbc != NULL)
2224         {
2225 	  /*
2226 	   * Dead connection was taken from pool
2227 	   */
2228 
2229           if (pdbc->cp_pdbc->cp_retry_wait != 0)
2230 	    {
2231 	      /*
2232 	       * Retry Wait timeout has not expired yet
2233 	       */
2234               PUSHSQLERR (pdbc->herr, en_08004);
2235 	      RETURN (SQL_ERROR);
2236 	    }
2237 
2238 	  /*
2239 	   * Free connection parameters.
2240 	   */
2241 	  if (waMode == 'W')
2242 	    {
2243 	      if (_szUID != NULL)
2244 	        {
2245 		  MEM_FREE (_szUID);
2246 		  _szUID = NULL;
2247 	        }
2248 	      if (_szAuthStr != NULL)
2249 	        {
2250 		  MEM_FREE (_szAuthStr);
2251 		  _szAuthStr = NULL;
2252 	        }
2253 	    }
2254 	}
2255       else
2256         {
2257           /*
2258 	   * Connection was not found in the pool --
2259 	   * save connection parameters
2260 	   */
2261 	  if (pdbc->cp_dsn != NULL)
2262 	    MEM_FREE (pdbc->cp_dsn);
2263 	  if (pdbc->cp_uid != NULL)
2264 	    MEM_FREE (pdbc->cp_uid);
2265 	  if (pdbc->cp_pwd != NULL)
2266 	    MEM_FREE (pdbc->cp_pwd);
2267 
2268           if (waMode == 'W')
2269 	    {
2270 	      pdbc->cp_dsn = _szDSN;
2271 	      _szDSN = NULL;
2272 	      pdbc->cp_uid = _szUID;
2273 	      _szUID = NULL;
2274 	      pdbc->cp_pwd = _szAuthStr;
2275 	      _szAuthStr = NULL;
2276 	    }
2277 	  else
2278 	    {
2279 	      pdbc->cp_dsn = strdup ((char *)_dsn);
2280 	      if (pdbc->cp_dsn == NULL)
2281 	        {
2282 		  PUSHSQLERR (pdbc->herr, en_S1001);
2283 		  RETURN (SQL_ERROR);
2284 		}
2285 	      if (_uid != NULL)
2286 	        {
2287 		  pdbc->cp_uid = strdup (_uid);
2288 		  if (pdbc->cp_uid == NULL)
2289 		    {
2290 		      PUSHSQLERR (pdbc->herr, en_S1001);
2291 		      RETURN (SQL_ERROR);
2292 		    }
2293 		}
2294 	      if (_pwd != NULL)
2295 	        {
2296 		  pdbc->cp_pwd = strdup (_pwd);
2297 		  if (pdbc->cp_pwd == NULL)
2298 		    {
2299 		      PUSHSQLERR (pdbc->herr, en_S1001);
2300 		      RETURN (SQL_ERROR);
2301 		    }
2302 		}
2303 	    }
2304 	}
2305     }
2306 #endif /* (ODBCVER >= 0x300) */
2307 
2308   /*
2309    *  Check whether driver is thread safe
2310    */
2311   thread_safe = 1;		/* Assume driver is thread safe */
2312 
2313   SQLSetConfigMode (ODBC_BOTH_DSN);
2314   if ( SQLGetPrivateProfileString ((char *) _dsn, "ThreadManager", "",
2315 	buf, sizeof(buf), "odbc.ini") &&
2316       (STRCASEEQ (buf, "on") || STRCASEEQ (buf, "1")))
2317     {
2318       thread_safe = 0;	/* Driver needs a thread manager */
2319     }
2320 
2321   /*
2322    *  Check if it is safe to unload the driver
2323    */
2324   unload_safe = 0;		/* Assume driver is not unload safe */
2325 
2326   SQLSetConfigMode (ODBC_BOTH_DSN);
2327   if ( SQLGetPrivateProfileString ((char *) _dsn, "UnloadSafe", "",
2328 	buf, sizeof(buf), "odbc.ini") &&
2329       (STRCASEEQ (buf, "on") || STRCASEEQ (buf, "1")))
2330     {
2331       unload_safe = 1;
2332     }
2333 
2334 
2335   /*
2336    *  Get the name of the driver module and load it
2337    */
2338   SQLSetConfigMode (ODBC_BOTH_DSN);
2339   if ( SQLGetPrivateProfileString ((char *) _dsn, "Driver", "",
2340 	(char *) driver, sizeof(driver), "odbc.ini") == 0)
2341     /* No specified or default dsn section or
2342      * no driver specification in this dsn section */
2343     {
2344       PUSHSQLERR (pdbc->herr, en_IM002);
2345       RETURN (SQL_ERROR);
2346     }
2347 
2348   retcode = _iodbcdm_driverload ((char *)_dsn, (char *)driver, pdbc, thread_safe, unload_safe, drv_cp, waMode);
2349 
2350   MEM_FREE(_szDSN);
2351   _szDSN = NULL;
2352 
2353   switch (retcode)
2354     {
2355     case SQL_SUCCESS:
2356       break;
2357 
2358     case SQL_SUCCESS_WITH_INFO:
2359 #if 0
2360       /*
2361        *  Unsuccessful in calling driver's SQLSetConnectOption() to set
2362        *  login timeout.
2363        */
2364       setopterr = SQL_ERROR;
2365 #endif
2366       break;
2367 
2368     default:
2369       return retcode;
2370     }
2371 
2372   penv = (ENV_t *) pdbc->henv;
2373   conv = &pdbc->conv;
2374 
2375   if (penv->unicode_driver && waMode != 'W')
2376     conv_direct = CD_A2W;
2377   else if (!penv->unicode_driver && waMode == 'W')
2378     conv_direct = CD_W2A;
2379   else if (waMode == 'W' && conv->dm_cp!=conv->drv_cp)
2380     conv_direct = CD_W2W;
2381 
2382   if (conv_direct != CD_NONE)
2383     {
2384       _szDSN = conv_text_m2d (conv, szDSN, cbDSN, conv_direct);
2385       _szUID = conv_text_m2d (conv, szUID, cbUID, conv_direct);
2386       _szAuthStr = conv_text_m2d (conv, szAuthStr, cbAuthStr, conv_direct);
2387       cbDSN = SQL_NTS;
2388       cbUID = SQL_NTS;
2389       cbAuthStr = SQL_NTS;
2390       szDSN = _szDSN;
2391       szUID = _szUID;
2392       szAuthStr = _szAuthStr;
2393     }
2394 
2395   ODBC_UNLOCK ();
2396   CALL_UDRIVER(hdbc, pdbc, retcode, hproc, penv->unicode_driver,
2397     en_Connect, (
2398        pdbc->dhdbc,
2399        szDSN,
2400        cbDSN,
2401        szUID,
2402        cbUID,
2403        szAuthStr,
2404        cbAuthStr));
2405   ODBC_LOCK ();
2406 
2407   if (hproc == SQL_NULL_HPROC)
2408     {
2409       _iodbcdm_driverunload (pdbc, 3);
2410       PUSHSQLERR (pdbc->herr, en_IM001);
2411       RETURN (SQL_ERROR);
2412     }
2413 
2414   if (!SQL_SUCCEEDED (retcode))
2415     {
2416       /* not unload driver for retrieve error
2417        * message from driver */
2418 		/*********
2419 		_iodbcdm_driverunload( hdbc , 3);
2420 		**********/
2421 
2422       RETURN (retcode);
2423     }
2424 
2425   /* state transition */
2426   pdbc->state = en_dbc_connected;
2427 
2428   /* do delayed option setting */
2429   setopterr |= _iodbcdm_dbcdelayset (pdbc, waMode);
2430 
2431   if (setopterr != SQL_SUCCESS)
2432     retcode = SQL_SUCCESS_WITH_INFO;
2433 
2434 end:
2435 #if (ODBCVER >= 0x300)
2436   if (!SQL_SUCCEEDED (retcode) &&
2437       pdbc->cp_pdbc != NULL)
2438     {
2439       int rc;
2440 
2441       /*
2442        * Dead connection was taken from the pool
2443        * but reconnection attempt has failed:
2444        * set cp_retry_wait time and return connection to the pool.
2445        */
2446       _iodbcdm_pool_set_retry_wait (pdbc);
2447       rc = _iodbcdm_pool_put_conn (pdbc);
2448       assert (rc == 0);
2449     }
2450 #endif
2451   if (_szDSN != NULL)
2452     MEM_FREE(_szDSN);
2453   if (_szUID != NULL)
2454     MEM_FREE (_szUID);
2455   if (_szAuthStr != NULL)
2456     MEM_FREE (_szAuthStr);
2457 
2458   return retcode;
2459 }
2460 
2461 
2462 SQLRETURN SQL_API
SQLConnect(SQLHDBC hdbc,SQLCHAR * szDSN,SQLSMALLINT cbDSN,SQLCHAR * szUID,SQLSMALLINT cbUID,SQLCHAR * szAuthStr,SQLSMALLINT cbAuthStr)2463 SQLConnect (
2464   SQLHDBC		  hdbc,
2465   SQLCHAR 		* szDSN,
2466   SQLSMALLINT		  cbDSN,
2467   SQLCHAR 		* szUID,
2468   SQLSMALLINT		  cbUID,
2469   SQLCHAR 		* szAuthStr,
2470   SQLSMALLINT		  cbAuthStr)
2471 {
2472   ENTER_HDBC (hdbc, 1,
2473     trace_SQLConnect (TRACE_ENTER,
2474     	hdbc,
2475 	szDSN, cbDSN,
2476 	szUID, cbUID,
2477 	szAuthStr, cbAuthStr));
2478 
2479   retcode =  SQLConnect_Internal (
2480   	hdbc,
2481 	szDSN, cbDSN,
2482 	szUID, cbUID,
2483 	szAuthStr, cbAuthStr, 'A');
2484 
2485   LEAVE_HDBC (hdbc, 1,
2486     trace_SQLConnect (TRACE_LEAVE,
2487     	hdbc,
2488 	szDSN, cbDSN,
2489 	szUID, cbUID,
2490 	szAuthStr, cbAuthStr));
2491 }
2492 
2493 
2494 SQLRETURN SQL_API
SQLConnectA(SQLHDBC hdbc,SQLCHAR * szDSN,SQLSMALLINT cbDSN,SQLCHAR * szUID,SQLSMALLINT cbUID,SQLCHAR * szAuthStr,SQLSMALLINT cbAuthStr)2495 SQLConnectA (
2496   SQLHDBC		  hdbc,
2497   SQLCHAR 		* szDSN,
2498   SQLSMALLINT		  cbDSN,
2499   SQLCHAR 		* szUID,
2500   SQLSMALLINT		  cbUID,
2501   SQLCHAR 		* szAuthStr,
2502   SQLSMALLINT		  cbAuthStr)
2503 {
2504   ENTER_HDBC (hdbc, 1,
2505     trace_SQLConnect (TRACE_ENTER,
2506     	hdbc,
2507 	szDSN, cbDSN,
2508 	szUID, cbUID,
2509 	szAuthStr, cbAuthStr));
2510 
2511   retcode =  SQLConnect_Internal (
2512   	hdbc,
2513 	szDSN, cbDSN,
2514 	szUID, cbUID,
2515 	szAuthStr, cbAuthStr, 'A');
2516 
2517   LEAVE_HDBC (hdbc, 1,
2518     trace_SQLConnect (TRACE_LEAVE,
2519     	hdbc,
2520 	szDSN, cbDSN,
2521 	szUID, cbUID,
2522 	szAuthStr, cbAuthStr));
2523 }
2524 
2525 
2526 SQLRETURN SQL_API
SQLConnectW(SQLHDBC hdbc,SQLWCHAR * szDSN,SQLSMALLINT cbDSN,SQLWCHAR * szUID,SQLSMALLINT cbUID,SQLWCHAR * szAuthStr,SQLSMALLINT cbAuthStr)2527 SQLConnectW (SQLHDBC hdbc,
2528     SQLWCHAR * szDSN,
2529     SQLSMALLINT cbDSN,
2530     SQLWCHAR * szUID,
2531     SQLSMALLINT cbUID,
2532     SQLWCHAR * szAuthStr,
2533     SQLSMALLINT cbAuthStr)
2534 {
2535   ENTER_HDBC (hdbc, 1,
2536     trace_SQLConnectW (TRACE_ENTER,
2537     	hdbc,
2538 	szDSN, cbDSN,
2539 	szUID, cbUID,
2540 	szAuthStr, cbAuthStr));
2541 
2542   retcode =  SQLConnect_Internal (
2543   	hdbc,
2544 	szDSN, cbDSN,
2545 	szUID, cbUID,
2546 	szAuthStr, cbAuthStr,
2547 	'W');
2548 
2549   LEAVE_HDBC (hdbc, 1,
2550     trace_SQLConnectW (TRACE_LEAVE,
2551     	hdbc,
2552 	szDSN, cbDSN,
2553 	szUID, cbUID,
2554 	szAuthStr, cbAuthStr));
2555 }
2556 
2557 
2558 SQLRETURN SQL_API
SQLDriverConnect_Internal(SQLHDBC hdbc,SQLHWND hwnd,SQLPOINTER szConnStrIn,SQLSMALLINT cbConnStrIn,SQLPOINTER szConnStrOut,SQLSMALLINT cbConnStrOutMax,SQLPOINTER pcbConnStrOut,SQLUSMALLINT fDriverCompletion,SQLCHAR waMode)2559 SQLDriverConnect_Internal (
2560     SQLHDBC hdbc,
2561     SQLHWND hwnd,
2562     SQLPOINTER szConnStrIn,
2563     SQLSMALLINT cbConnStrIn,
2564     SQLPOINTER szConnStrOut,
2565     SQLSMALLINT cbConnStrOutMax,
2566     SQLPOINTER pcbConnStrOut,
2567     SQLUSMALLINT fDriverCompletion,
2568     SQLCHAR waMode)
2569 {
2570   CONN (pdbc, hdbc);
2571   ENVR (penv, NULL);
2572 #if (ODBCVER >= 0x300)
2573   GENV (genv, NULL);
2574 #endif
2575   HDLL hdll = NULL;
2576   SQLCHAR *drv = NULL;
2577   SQLCHAR drvbuf[1024];
2578   SQLCHAR *dsn = NULL;
2579   SQLCHAR dsnbuf[SQL_MAX_DSN_LENGTH + 1];
2580   SQLWCHAR prov[2048];
2581   SQLWCHAR StrInTmp[2048];
2582   SWORD thread_safe;
2583   SWORD unload_safe;
2584   SQLCHAR buf[1024];
2585   HPROC hproc = SQL_NULL_HPROC;
2586   void *_ConnStrIn = NULL;
2587   void *_ConnStrOut = NULL;
2588   void *connStrOut = szConnStrOut;
2589   void *connStrIn = szConnStrIn;
2590   SQLSMALLINT connStrOutMax = cbConnStrOutMax;
2591   SQLWCHAR connStrOut_buf[2048];
2592   SQLWCHAR connStrIn_buf[2048];
2593   UWORD config;
2594   PCONFIG pconfig = NULL;
2595   BOOL bCallDmDlg = FALSE;
2596 #if defined (__APPLE__) && !defined (NO_FRAMEWORKS)
2597   CFBundleRef bundle = NULL;
2598   CFBundleRef bundle_dll = NULL;
2599   CFURLRef liburl = NULL;
2600 #endif
2601   SQLCHAR *filedsn = NULL;
2602   SQLCHAR *savefile = NULL;
2603   CONV_DIRECT conv_direct = CD_NONE;
2604   DM_CONV *conv = NULL;
2605   IODBC_CHARSET drv_cp = CP_DEF;
2606 
2607   HPROC dialproc = SQL_NULL_HPROC;
2608 
2609   sqlstcode_t sqlstat = en_00000;
2610   SQLRETURN retcode = SQL_SUCCESS;
2611   SQLRETURN setopterr = SQL_SUCCESS;
2612 
2613   /* check arguments */
2614   if ((cbConnStrIn < 0 && cbConnStrIn != SQL_NTS) ||
2615       (cbConnStrOutMax < 0 && cbConnStrOutMax != SQL_NTS))
2616     {
2617       PUSHSQLERR (pdbc->herr, en_S1090);
2618       RETURN (SQL_ERROR);
2619     }
2620 
2621   /* check state */
2622   if (pdbc->state != en_dbc_allocated)
2623     {
2624       PUSHSQLERR (pdbc->herr, en_08002);
2625       RETURN (SQL_ERROR);
2626     }
2627 
2628   /* Save config mode */
2629   SQLGetConfigMode (&config);
2630 
2631   conv = (penv != SQL_NULL_HENV) ? &penv->conv : &((GENV_t *) pdbc->genv)->conv;
2632 
2633   if (_iodbcdm_cfg_init_str (&pconfig, connStrIn, cbConnStrIn,
2634 			     waMode == 'W', conv) == -1)
2635     {
2636       PUSHSQLERR (pdbc->herr, en_HY001);
2637       RETURN (SQL_ERROR);
2638     }
2639   assert (_iodbcdm_cfg_valid(pconfig));
2640 
2641   /* lookup and save original SAVEFILE value */
2642   if (_iodbcdm_cfg_find (pconfig, "ODBC", "SAVEFILE") == 0)
2643     {
2644       savefile = (SQLCHAR *)strdup (pconfig->value);
2645       if (savefile == NULL)
2646         {
2647           PUSHSQLERR (pdbc->herr, en_HY001);
2648           RETURN (SQL_ERROR);
2649         }
2650     }
2651 
2652 
2653 #if (ODBCVER >= 0x300)
2654   genv = (GENV_t *) pdbc->genv;
2655 
2656   /*
2657    * Try to find pooled connection.
2658    * Pooling is disabled if SAVEFILE is present.
2659    */
2660   if (genv->connection_pooling != SQL_CP_OFF && savefile == NULL)
2661     {
2662       char *_connstr = connStrIn;
2663 
2664       if (fDriverCompletion != SQL_DRIVER_NOPROMPT)
2665         {
2666           PUSHSQLERR (pdbc->herr, en_HY110);
2667           RETURN (SQL_ERROR);
2668         }
2669 
2670       if (waMode == 'W')
2671         {
2672           _ConnStrIn = DM_WtoU8(conv, (SQLWCHAR *) connStrIn, cbConnStrIn);
2673 	  if (_ConnStrIn == NULL)
2674 	    {
2675               PUSHSQLERR (pdbc->herr, en_HY001);
2676               RETURN (SQL_ERROR);
2677 	    }
2678 	  _connstr = _ConnStrIn;
2679 	}
2680 
2681       retcode = _iodbcdm_pool_get_conn (pdbc, NULL, NULL, NULL, _connstr);
2682       if (SQL_SUCCEEDED (retcode))
2683         {
2684 	  /*
2685 	   * Got connection from the pool
2686 	   */
2687 
2688           /* copy out connection string */
2689           if (szConnStrOut != NULL)
2690 	    {
2691 	      if (waMode == 'W')
2692 		{
2693 		  DM_WCSNCPY (conv, szConnStrOut, szConnStrIn, cbConnStrOutMax);
2694 
2695 		  if (pcbConnStrOut != NULL)
2696 		    {
2697 		      if (conv && conv->dm_cp == CP_UTF8)
2698 			*(SQLSMALLINT *) pcbConnStrOut = strlen ((char *) szConnStrOut);
2699 		      else
2700 			*(SQLSMALLINT *) pcbConnStrOut = DM_WCSLEN (conv, szConnStrOut);
2701 		    }
2702 		}
2703 	      else
2704 		{
2705 		  _iodbcdm_strlcpy (szConnStrOut, szConnStrIn, cbConnStrOutMax);
2706 		  if (pcbConnStrOut != NULL)
2707 		    *(SQLSMALLINT *) pcbConnStrOut = strlen (szConnStrOut);
2708 		}
2709 	    }
2710 
2711           /* state transition */
2712           pdbc->state = en_dbc_connected;
2713 
2714           RETURN (retcode);
2715         }
2716 
2717       if (pdbc->cp_pdbc != NULL)
2718         {
2719 	  /*
2720 	   * Dead connection was taken from pool
2721 	   */
2722 
2723           if (pdbc->cp_pdbc->cp_retry_wait != 0)
2724 	    {
2725 	      /*
2726 	       * Retry Wait timeout has not expired yet
2727 	       */
2728               PUSHSQLERR (pdbc->herr, en_08004);
2729 	      RETURN (SQL_ERROR);
2730 	    }
2731 
2732 	  /*
2733 	   * Free connection parameters.
2734 	   */
2735 	  if (waMode == 'W')
2736 	    {
2737 	      if (_ConnStrIn != NULL)
2738 	        {
2739 		  MEM_FREE (_ConnStrIn);
2740 		  _ConnStrIn = NULL;
2741 	        }
2742 	    }
2743         }
2744       else
2745         {
2746           /*
2747 	   * Connection was not found in the pool --
2748 	   * save connection parameters
2749 	   */
2750 	  if (pdbc->cp_connstr != NULL)
2751 	    MEM_FREE (pdbc->cp_connstr);
2752 
2753           if (waMode == 'W')
2754 	    {
2755 	      pdbc->cp_connstr = _ConnStrIn;
2756 	      _ConnStrIn = NULL;
2757 	    }
2758 	  else
2759 	    {
2760               pdbc->cp_connstr = strdup (_connstr);
2761 	      if (pdbc->cp_connstr == NULL)
2762 	        {
2763                   PUSHSQLERR (pdbc->herr, en_HY001);
2764                   RETURN (SQL_ERROR);
2765 	        }
2766 	    }
2767         }
2768     }
2769 #endif /* (ODBCVER >= 0x300) */
2770 
2771   /* always get (even if not requested) out connection string for SAVEFILE */
2772   if (!connStrOut)
2773     {
2774       connStrOut = connStrOut_buf;
2775       connStrOutMax = sizeof(connStrOut_buf);
2776     }
2777 
2778   /* now look for DSN or FILEDSN, whichever comes first */
2779   _iodbcdm_cfg_rewind (pconfig);
2780   while (_iodbcdm_cfg_nextentry (pconfig) == 0)
2781     {
2782       if (!_iodbcdm_cfg_define (pconfig))
2783         continue;
2784 
2785       if (!strcasecmp(pconfig->id, "DSN"))
2786         {
2787           /* not a file dsn */
2788           break;
2789         }
2790       else if (!strcasecmp(pconfig->id, "FILEDSN"))
2791         {
2792           /* file dsn */
2793           filedsn = (SQLCHAR *)strdup (pconfig->value);
2794 	  if (filedsn == NULL)
2795 	    {
2796               PUSHSQLERR (pdbc->herr, en_HY001);
2797               RETURN (SQL_ERROR);
2798 	    }
2799 	  break;
2800 	}
2801     }
2802 
2803 
2804   /* get connect parameters from .dsn file if requested */
2805   if (filedsn != NULL)
2806     {
2807       /* merge params from .dsn file */
2808       if (_iodbcdm_cfg_merge_filedsn (pconfig, (char *)filedsn,
2809 	      (char *) connStrIn_buf, sizeof (connStrIn_buf),
2810 	      waMode == 'W', conv) == -1)
2811         {
2812           PUSHSQLERR (pdbc->herr, en_IM015);
2813           RETURN (SQL_ERROR);
2814 	}
2815 
2816       /* update connection string and its length */
2817       connStrIn = connStrIn_buf;
2818       if (cbConnStrIn != SQL_NTS)
2819 	{
2820 	  if (waMode != 'W')
2821 	    cbConnStrIn = STRLEN (connStrIn);
2822 	  else
2823 	    cbConnStrIn = DM_WCSLEN (conv, connStrIn);
2824 	}
2825     }
2826 
2827   if (_iodbcdm_cfg_find (pconfig, "ODBC", "DRIVER") == 0)
2828     {
2829       /* copy because pconfig can be reinitialized later */
2830       _iodbcdm_strlcpy ((char *) drvbuf, pconfig->value, sizeof (drvbuf));
2831       drv = drvbuf;
2832     }
2833   if (_iodbcdm_cfg_find (pconfig, "ODBC", "DSN") == 0)
2834     {
2835       /* copy because pconfig can be reinitialized later */
2836       _iodbcdm_strlcpy ((char *) dsnbuf, pconfig->value, sizeof (dsnbuf));
2837       dsn = dsnbuf;
2838     }
2839 
2840   if (_iodbcdm_cfg_find (pconfig, "ODBC", "DriverUnicodeType") == 0)
2841     {
2842       if (STRCASEEQ(pconfig->value, "1") || STRCASEEQ(pconfig->value, "utf16"))
2843         drv_cp = CP_UTF16;
2844       else if (STRCASEEQ(pconfig->value, "2") || STRCASEEQ(pconfig->value, "utf8"))
2845         drv_cp = CP_UTF8;
2846       else if (STRCASEEQ(pconfig->value, "3") || STRCASEEQ(pconfig->value, "ucs4"))
2847         drv_cp = CP_UCS4;
2848 
2849       DPRINTF ((stderr,
2850        "DEBUG: SQLDriverConnect DriverUnicodeType=%s\n",
2851           drv_cp==CP_UCS4?"UCS4":(drv_cp==CP_UTF16?"UTF16":"UTF8")));
2852     }
2853 
2854   switch (fDriverCompletion)
2855     {
2856     case SQL_DRIVER_NOPROMPT:
2857       /* Check if there's a DSN or DRIVER */
2858       if (!dsn && !drv)
2859 	{
2860 	  PUSHSQLERR (pdbc->herr, en_IM007);
2861 	  RETURN (SQL_ERROR);
2862 	}
2863       break;
2864 
2865     case SQL_DRIVER_COMPLETE:
2866     case SQL_DRIVER_COMPLETE_REQUIRED:
2867       if (dsn != NULL || drv != NULL)
2868 	{
2869 	  break;
2870 	}
2871       /* fall to next case */
2872     case SQL_DRIVER_PROMPT:
2873       /* Get data source dialog box function from
2874        * current executable */
2875       /* Not really sure here, but should load that from the iodbcadm */
2876       if (waMode == 'A')
2877 	_iodbcdm_strlcpy ((char *) prov, connStrIn, sizeof (prov));
2878       else if (conv && conv->dm_cp == CP_UTF8)
2879 	_iodbcdm_strlcpy ((char *) prov, connStrIn, sizeof (prov));
2880       else
2881         DM_WCSNCPY (conv, prov, connStrIn, sizeof (prov) / DM_WCHARSIZE(conv));
2882 
2883 #if 0
2884         if (!dsn && !drv)
2885           bCallDmDlg = TRUE;
2886         else if ( _iodbcdm_CheckDriverLoginDlg(drv, dsn) == FALSE)
2887           bCallDmDlg = TRUE;
2888 
2889         /* not call iODBC function "iodbcdm_drvconn_dialbox", if there is
2890          * the function "_iodbcdm_drvconn_dialbox" in the odbc driver,
2891          * odbc driver must call its function itself
2892          */
2893         if (!bCallDmDlg)
2894           break;
2895 #endif
2896 
2897       ODBC_UNLOCK ();
2898 #if defined (__APPLE__)
2899 # if !defined(NO_FRAMEWORKS)
2900     bundle = CFBundleGetBundleWithIdentifier (CFSTR ("org.iodbc.core"));
2901     if (bundle)
2902       {
2903         /* Search for the drvproxy library */
2904         liburl =
2905             CFBundleCopyResourceURL (bundle, CFSTR ("iODBCadm.bundle"),
2906             NULL, NULL);
2907           if (liburl) {
2908               bundle_dll = CFBundleCreate (NULL, liburl);
2909               if (bundle_dll){
2910                   if (waMode != 'W')
2911                       dialproc = (HPROC)CFBundleGetFunctionPointerForName (bundle_dll, CFSTR("iodbcdm_drvconn_dialbox"));
2912                   else
2913                       dialproc = (HPROC)CFBundleGetFunctionPointerForName (bundle_dll, CFSTR("iodbcdm_drvconn_dialboxw"));
2914               }
2915           }
2916 
2917           if (liburl)
2918             CFRelease (liburl);
2919       }
2920       if (!bundle_dll)
2921           break;
2922 # endif
2923 #else
2924 
2925       hdll = _iodbcdm_dllopen ("libiodbcadm.so.2");
2926 
2927       if (!hdll)
2928          break;
2929 
2930       if (waMode != 'W')
2931         dialproc = _iodbcdm_dllproc (hdll, "iodbcdm_drvconn_dialbox");
2932       else
2933         dialproc = _iodbcdm_dllproc (hdll, "iodbcdm_drvconn_dialboxw");
2934 #endif
2935 
2936       if (dialproc == SQL_NULL_HPROC)
2937         {
2938           sqlstat = en_IM008;
2939           break;
2940         }
2941 
2942       {
2943         IODBC_CHARSET m_charset = (conv) ? conv->dm_cp : CP_DEF;
2944         ssize_t size = cbConnStrIn;
2945 
2946         /*** convert DM_WCHAR => SYS_WCHAR ***/
2947         if (waMode == 'A')
2948 	  _iodbcdm_strlcpy ((char *) prov, connStrIn, sizeof (prov));
2949         else
2950           {
2951             if (size == SQL_NTS)
2952               {
2953                 if (m_charset == CP_UTF8)
2954 	          size = strlen((char*) connStrIn);
2955                 else
2956 	          size = DM_WCSLEN (conv, connStrIn);
2957 	      }
2958 
2959 	    if (m_charset != CP_UTF8)
2960 	      size *= DM_WCHARSIZE(conv);
2961 
2962 	    if (size >= sizeof(prov))
2963 	      size = sizeof(prov) - DM_WCHARSIZE(conv);
2964 
2965             size = dm_conv_W2W(connStrIn, cbConnStrIn, prov,
2966 		sizeof(prov)-sizeof(SQLWCHAR), m_charset, CP_DEF);
2967             prov[size/sizeof(SQLWCHAR)] = L'\0';
2968           }
2969 
2970         retcode = dialproc (hwnd,	/* window or display handle */
2971           prov,		        /* input/output dsn buf */
2972           sizeof (prov) / (waMode == 'A' ? 1 : sizeof (SQLWCHAR)), /* buf size */
2973           &sqlstat,		/* error code */
2974           fDriverCompletion,	/* type of completion */
2975           &config);		/* config mode */
2976 
2977 
2978         ODBC_LOCK ();
2979         fDriverCompletion = SQL_DRIVER_NOPROMPT;
2980 
2981         if (retcode != SQL_SUCCESS)
2982           {
2983             if (retcode != SQL_NO_DATA_FOUND)
2984   	      PUSHSQLERR (pdbc->herr, sqlstat);
2985 	    goto end;
2986           }
2987 
2988         if (waMode == 'W')
2989           {
2990             /*** convert SYS_WCHAR => DM_WCHAR ***/
2991             size = dm_conv_W2W(prov, SQL_NTS, StrInTmp, sizeof(StrInTmp)-sizeof(SQLWCHAR),
2992           	CP_DEF, m_charset);
2993             StrInTmp[size/sizeof(SQLWCHAR)] = L'\0';
2994             connStrIn = StrInTmp;
2995           }
2996         else
2997           connStrIn = prov;
2998       }
2999 
3000       /*
3001        * Recalculate length of connStrIn if needed, as it may have been
3002        * changed by iodbcdm_drvconn_dialbox
3003        */
3004       if (cbConnStrIn != SQL_NTS)
3005         {
3006 	  if (waMode != 'W')
3007 	    cbConnStrIn = STRLEN (connStrIn);
3008 	  else
3009 	    cbConnStrIn = DM_WCSLEN (conv, connStrIn);
3010 	}
3011 
3012       if (_iodbcdm_cfg_parse_str (pconfig, connStrIn, cbConnStrIn,
3013 				  waMode == 'W', conv) == -1)
3014         {
3015           PUSHSQLERR (pdbc->herr, en_HY001);
3016           RETURN (SQL_ERROR);
3017         }
3018       if (_iodbcdm_cfg_find (pconfig, "ODBC", "DSN") == 0)
3019         dsn = (SQLCHAR *)pconfig->value;
3020       if (_iodbcdm_cfg_find (pconfig, "ODBC", "DRIVER") == 0)
3021         {
3022           /* copy because pconfig can be reinitialized later */
3023           _iodbcdm_strlcpy ((char *) drvbuf, pconfig->value, sizeof (drvbuf));
3024           drv = drvbuf;
3025         }
3026       if (_iodbcdm_cfg_find (pconfig, "ODBC", "DriverUnicodeType") == 0)
3027         {
3028           if (STRCASEEQ(pconfig->value, "1") || STRCASEEQ(pconfig->value, "utf16"))
3029             drv_cp = CP_UTF16;
3030           else if (STRCASEEQ(pconfig->value, "2") || STRCASEEQ(pconfig->value, "utf8"))
3031             drv_cp = CP_UTF8;
3032           else if (STRCASEEQ(pconfig->value, "3") || STRCASEEQ(pconfig->value, "ucs4"))
3033             drv_cp = CP_UCS4;
3034 
3035           DPRINTF ((stderr,
3036            "DEBUG: SQLDriverConnect DriverUnicodeType=%s\n",
3037               drv_cp==CP_UCS4?"UCS4":(drv_cp==CP_UTF16?"UTF16":"UTF8")));
3038         }
3039       break;
3040 
3041     default:
3042       sqlstat = en_S1110;
3043       break;
3044     }
3045 
3046   if (sqlstat != en_00000)
3047     {
3048       PUSHSQLERR (pdbc->herr, sqlstat);
3049       RETURN (SQL_ERROR);
3050     }
3051 
3052   if (dsn == NULL || *(char *) dsn == '\0')
3053     {
3054       dsn = (void *) "default";
3055     }
3056   else
3057     /* if you want tracing, you must use a DSN */
3058     {
3059       setopterr |=
3060           _iodbcdm_con_settracing (pdbc, (SQLCHAR *) dsn, SQL_NTS, waMode);
3061     }
3062 
3063   /*
3064    *  Check whether driver is thread safe
3065    */
3066   thread_safe = 1;		/* Assume driver is thread safe */
3067 
3068   SQLSetConfigMode (ODBC_BOTH_DSN);
3069   if (SQLGetPrivateProfileString ((char *) dsn, "ThreadManager", "",
3070 	(LPSTR)buf, sizeof (buf), "odbc.ini")
3071       && (STRCASEEQ (buf, "on") || STRCASEEQ (buf, "1")))
3072     {
3073       thread_safe = 0;		/* Driver needs a thread manager */
3074     }
3075 
3076   /*
3077    *  Check whether driver is unload safe
3078    */
3079   unload_safe = 0;		/* Assume driver is not unload safe */
3080 
3081   SQLSetConfigMode (ODBC_BOTH_DSN);
3082   if (SQLGetPrivateProfileString ((char *) dsn, "UnloadSafe", "",
3083 	(LPSTR)buf, sizeof (buf), "odbc.ini")
3084       && (STRCASEEQ (buf, "on") || STRCASEEQ (buf, "1")))
3085     {
3086       unload_safe = 1;
3087     }
3088 
3089   /*
3090    *  Get the name of the driver module
3091    */
3092   if (drv == NULL || *(char *) drv == '\0')
3093     {
3094       SQLSetConfigMode (ODBC_BOTH_DSN);
3095       if (SQLGetPrivateProfileString ((char *) dsn, "Driver", "",
3096 	      (char *) drvbuf, sizeof (drvbuf), "odbc.ini") != 0)
3097 	{
3098 	  drv = drvbuf;
3099 	}
3100     }
3101 
3102   if (drv == NULL)
3103     {
3104       PUSHSQLERR (pdbc->herr, en_IM002);
3105       RETURN (SQL_ERROR);
3106     }
3107 
3108   retcode =
3109       _iodbcdm_driverload ((char *)dsn, (char *) drv, pdbc, thread_safe, unload_safe,
3110       drv_cp, waMode);
3111 
3112   switch (retcode)
3113     {
3114     case SQL_SUCCESS:
3115       break;
3116 
3117     case SQL_SUCCESS_WITH_INFO:
3118 #if 0
3119       /*
3120        *  Unsuccessful in calling driver's SQLSetConnectOption() to set
3121        *  login timeout.
3122        */
3123       setopterr = SQL_ERROR;
3124 #endif
3125       break;
3126 
3127     default:
3128       RETURN (retcode);
3129     }
3130 
3131 #if (ODBCVER >= 0x300)
3132   /*
3133    * Pooling is disabled if SAVEFILE is present.
3134    */
3135   if (savefile != NULL)
3136     pdbc->cp_timeout = 0;
3137 #endif
3138 
3139   penv = (ENV_t *) pdbc->henv;
3140   conv = &pdbc->conv;
3141 
3142   if (penv->unicode_driver && waMode != 'W')
3143     conv_direct = CD_A2W;
3144   else if (!penv->unicode_driver && waMode == 'W')
3145     conv_direct = CD_W2A;
3146   else if (waMode == 'W' && conv->dm_cp!=conv->drv_cp)
3147     conv_direct = CD_W2W;
3148 
3149   if (conv_direct != CD_NONE)
3150     {
3151       if ((_ConnStrOut =
3152 	      malloc ((connStrOutMax + 1) * WCHAR_MAXSIZE)) == NULL)
3153 	{
3154 	  PUSHSQLERR (pdbc->herr, en_HY001);
3155 	  RETURN (SQL_ERROR);
3156 	}
3157       _ConnStrIn = conv_text_m2d (conv, connStrIn, cbConnStrIn, conv_direct);
3158 
3159       connStrOut = _ConnStrOut;
3160       connStrIn = _ConnStrIn;
3161       cbConnStrIn = SQL_NTS;
3162     }
3163 
3164   /* Restore config mode */
3165   SQLSetConfigMode (config);
3166 
3167   ODBC_UNLOCK ();
3168   CALL_UDRIVER (hdbc, pdbc, retcode, hproc, penv->unicode_driver,
3169       en_DriverConnect, (pdbc->dhdbc,
3170 	  hwnd,
3171 	  connStrIn,
3172 	  cbConnStrIn,
3173 	  connStrOut, connStrOutMax, pcbConnStrOut, fDriverCompletion));
3174   ODBC_LOCK ();
3175 
3176   if (hproc == SQL_NULL_HPROC)
3177     {
3178       _iodbcdm_driverunload (pdbc, 3);
3179       PUSHSQLERR (pdbc->herr, en_IM001);
3180       RETURN (SQL_ERROR);
3181     }
3182 
3183   if (szConnStrOut && SQL_SUCCEEDED (retcode) && conv_direct != CD_NONE)
3184     {
3185       if (conv_direct == CD_A2W)
3186         {
3187 	  /* ansi<=unicode */
3188           dm_StrCopyOut2_W2A_d2m (conv, connStrOut,
3189               (SQLCHAR *) szConnStrOut, cbConnStrOutMax, NULL, NULL);
3190         }
3191       else if (conv_direct == CD_W2A)
3192         {
3193 	  /* unicode<=ansi */
3194           dm_StrCopyOut2_A2W_d2m (conv, (SQLCHAR *) connStrOut,
3195               szConnStrOut, cbConnStrOutMax * DM_WCHARSIZE(conv), NULL, NULL);
3196         }
3197       else if (conv_direct == CD_W2W)
3198         {
3199 	  /* unicode<=unicode */
3200           dm_StrCopyOut2_W2W_d2m (conv, connStrOut,
3201               szConnStrOut, cbConnStrOutMax * DM_WCHARSIZE(conv), NULL, NULL);
3202         }
3203     }
3204 
3205   if (szConnStrOut != NULL)
3206     {
3207       if (filedsn != NULL)
3208         {
3209           /* append FILEDSN to the out connection string */
3210           if (waMode == 'W')
3211             {
3212               char tmp[4096] = {""};
3213               size_t outSize = DM_WCSLEN(conv, szConnStrOut);
3214               char *out = szConnStrOut;
3215 
3216               out += outSize * DM_WCHARSIZE(conv);
3217 
3218               _iodbcdm_strlcat (tmp, ";FILEDSN=", sizeof(tmp));
3219               _iodbcdm_strlcat (tmp, (char *)filedsn, sizeof(tmp));
3220               dm_StrCopyOut2_U8toW_d2m(conv, (SQLCHAR *)tmp, out,
3221 			(cbConnStrOutMax - outSize) * DM_WCHARSIZE(conv),
3222 			NULL, NULL);
3223 	    }
3224           else
3225             {
3226               _iodbcdm_strlcat (szConnStrOut, ";FILEDSN=", cbConnStrOutMax);
3227               _iodbcdm_strlcat (szConnStrOut, (char *)filedsn, cbConnStrOutMax);
3228             }
3229         }
3230       if (savefile != NULL)
3231         {
3232           /* append SAVEFILE to the out connection string */
3233           if (waMode == 'W')
3234             {
3235               char tmp[4096] = {""};
3236               size_t outSize = DM_WCSLEN(conv, szConnStrOut);
3237               char *out = szConnStrOut;
3238 
3239               out += outSize * DM_WCHARSIZE(conv);
3240 
3241               _iodbcdm_strlcat (tmp, ";SAVEFILE=", sizeof(tmp));
3242               _iodbcdm_strlcat (tmp, (char *)savefile, sizeof(tmp));
3243               dm_StrCopyOut2_U8toW_d2m(conv, (SQLCHAR *)tmp, out,
3244 			(cbConnStrOutMax - outSize) * DM_WCHARSIZE(conv),
3245 			NULL, NULL);
3246 	    }
3247           else
3248             {
3249               _iodbcdm_strlcat (szConnStrOut, ";SAVEFILE=", cbConnStrOutMax);
3250               _iodbcdm_strlcat (szConnStrOut, (char *)savefile, cbConnStrOutMax);
3251             }
3252         }
3253 
3254       /* fixup pcbConnStrOut */
3255       if (pcbConnStrOut != NULL)
3256 	{
3257 	  if (waMode == 'W')
3258 	    *(SQLSMALLINT *) pcbConnStrOut = DM_WCSLEN (conv, szConnStrOut);
3259 	  else
3260 	    *(SQLSMALLINT *) pcbConnStrOut = strlen (szConnStrOut);
3261 	}
3262     }
3263 
3264   if (!SQL_SUCCEEDED (retcode))
3265     {
3266       /* don't unload driver here for retrieve
3267        * error message from driver */
3268 		/********
3269 		_iodbcdm_driverunload( hdbc , 3);
3270 		*********/
3271 
3272       RETURN (retcode);
3273     }
3274 
3275   /* state transition */
3276   pdbc->state = en_dbc_connected;
3277 
3278   /* do delayed option setting */
3279   setopterr |= _iodbcdm_dbcdelayset (pdbc, waMode);
3280 
3281   if (setopterr != SQL_SUCCESS)
3282     retcode = SQL_SUCCESS_WITH_INFO;
3283 
3284   /* save .dsn file if requested */
3285   if (savefile != NULL)
3286     {
3287       assert (connStrOut != NULL);
3288 
3289       if (_iodbcdm_cfg_savefile ((char *)savefile, connStrOut,
3290 				 penv->unicode_driver, conv) == -1)
3291         {
3292 	  PUSHSQLERR (pdbc->herr, en_01S08);
3293 	  retcode = SQL_SUCCESS_WITH_INFO;
3294 	}
3295     }
3296 
3297 end:
3298 #if (ODBCVER >= 0x300)
3299   if (!SQL_SUCCEEDED (retcode) &&
3300       pdbc->cp_pdbc != NULL)
3301     {
3302       int rc;
3303 
3304       /*
3305        * Dead connection was taken from the pool
3306        * but reconnection attempt has failed:
3307        * set cp_retry_wait time and return connection to the pool.
3308        */
3309       _iodbcdm_pool_set_retry_wait (pdbc);
3310       rc = _iodbcdm_pool_put_conn (pdbc);
3311       assert (rc == 0);
3312     }
3313 #endif
3314   _iodbcdm_cfg_done (pconfig);
3315   if (_ConnStrIn != NULL)
3316     MEM_FREE (_ConnStrIn);
3317   if (_ConnStrOut != NULL)
3318     MEM_FREE (_ConnStrOut);
3319   if (savefile != NULL)
3320     MEM_FREE (savefile);
3321   if (filedsn != NULL)
3322     MEM_FREE (filedsn);
3323 
3324   return retcode;
3325 }
3326 
3327 
3328 SQLRETURN SQL_API
SQLDriverConnect(SQLHDBC hdbc,SQLHWND hwnd,SQLCHAR * szConnStrIn,SQLSMALLINT cbConnStrIn,SQLCHAR * szConnStrOut,SQLSMALLINT cbConnStrOutMax,SQLSMALLINT * pcbConnStrOut,SQLUSMALLINT fDriverCompletion)3329 SQLDriverConnect (SQLHDBC hdbc,
3330     SQLHWND hwnd,
3331     SQLCHAR * szConnStrIn,
3332     SQLSMALLINT cbConnStrIn,
3333     SQLCHAR * szConnStrOut,
3334     SQLSMALLINT cbConnStrOutMax,
3335     SQLSMALLINT * pcbConnStrOut,
3336     SQLUSMALLINT fDriverCompletion)
3337 {
3338   ENTER_HDBC (hdbc, 1,
3339     trace_SQLDriverConnect (TRACE_ENTER,
3340 	hdbc,
3341 	hwnd,
3342 	szConnStrIn, cbConnStrIn,
3343 	szConnStrOut, cbConnStrOutMax, pcbConnStrOut,
3344 	fDriverCompletion));
3345 
3346   retcode = SQLDriverConnect_Internal(
3347       hdbc,
3348       hwnd,
3349       szConnStrIn, cbConnStrIn,
3350       szConnStrOut, cbConnStrOutMax, pcbConnStrOut,
3351       fDriverCompletion,
3352       'A');
3353 
3354   LEAVE_HDBC (hdbc, 1,
3355     trace_SQLDriverConnect (TRACE_LEAVE,
3356 	hdbc,
3357 	hwnd,
3358 	szConnStrIn, cbConnStrIn,
3359 	szConnStrOut, cbConnStrOutMax, pcbConnStrOut,
3360 	fDriverCompletion));
3361 }
3362 
3363 
3364 SQLRETURN SQL_API
SQLDriverConnectA(SQLHDBC hdbc,SQLHWND hwnd,SQLCHAR * szConnStrIn,SQLSMALLINT cbConnStrIn,SQLCHAR * szConnStrOut,SQLSMALLINT cbConnStrOutMax,SQLSMALLINT * pcbConnStrOut,SQLUSMALLINT fDriverCompletion)3365 SQLDriverConnectA (SQLHDBC hdbc,
3366     SQLHWND hwnd,
3367     SQLCHAR * szConnStrIn,
3368     SQLSMALLINT cbConnStrIn,
3369     SQLCHAR * szConnStrOut,
3370     SQLSMALLINT cbConnStrOutMax,
3371     SQLSMALLINT * pcbConnStrOut,
3372     SQLUSMALLINT fDriverCompletion)
3373 {
3374   ENTER_HDBC (hdbc, 1,
3375     trace_SQLDriverConnect (TRACE_ENTER,
3376 	hdbc,
3377 	hwnd,
3378 	szConnStrIn, cbConnStrIn,
3379 	szConnStrOut, cbConnStrOutMax, pcbConnStrOut,
3380 	fDriverCompletion));
3381 
3382   retcode = SQLDriverConnect_Internal(
3383       hdbc,
3384       hwnd,
3385       szConnStrIn, cbConnStrIn,
3386       szConnStrOut, cbConnStrOutMax, pcbConnStrOut,
3387       fDriverCompletion,
3388       'A');
3389 
3390   LEAVE_HDBC (hdbc, 1,
3391     trace_SQLDriverConnect (TRACE_LEAVE,
3392 	hdbc,
3393 	hwnd,
3394 	szConnStrIn, cbConnStrIn,
3395 	szConnStrOut, cbConnStrOutMax, pcbConnStrOut,
3396 	fDriverCompletion));
3397 }
3398 
3399 
3400 SQLRETURN SQL_API
SQLDriverConnectW(SQLHDBC hdbc,SQLHWND hwnd,SQLWCHAR * szConnStrIn,SQLSMALLINT cbConnStrIn,SQLWCHAR * szConnStrOut,SQLSMALLINT cbConnStrOutMax,SQLSMALLINT * pcbConnStrOut,SQLUSMALLINT fDriverCompletion)3401 SQLDriverConnectW (SQLHDBC hdbc,
3402     SQLHWND hwnd,
3403     SQLWCHAR * szConnStrIn,
3404     SQLSMALLINT cbConnStrIn,
3405     SQLWCHAR * szConnStrOut,
3406     SQLSMALLINT cbConnStrOutMax,
3407     SQLSMALLINT * pcbConnStrOut,
3408     SQLUSMALLINT fDriverCompletion)
3409 {
3410   ENTER_HDBC (hdbc, 1,
3411     trace_SQLDriverConnectW (TRACE_ENTER,
3412 	hdbc,
3413 	hwnd,
3414 	szConnStrIn, cbConnStrIn,
3415 	szConnStrOut, cbConnStrOutMax, pcbConnStrOut,
3416 	fDriverCompletion));
3417 
3418   retcode = SQLDriverConnect_Internal(
3419       hdbc,
3420       hwnd,
3421       szConnStrIn, cbConnStrIn,
3422       szConnStrOut, cbConnStrOutMax, pcbConnStrOut,
3423       fDriverCompletion,
3424       'W');
3425 
3426   LEAVE_HDBC (hdbc, 1,
3427     trace_SQLDriverConnectW (TRACE_LEAVE,
3428 	hdbc,
3429 	hwnd,
3430 	szConnStrIn, cbConnStrIn,
3431 	szConnStrOut, cbConnStrOutMax, pcbConnStrOut,
3432 	fDriverCompletion));
3433 }
3434 
3435 
3436 SQLRETURN SQL_API
SQLBrowseConnect_Internal(SQLHDBC hdbc,SQLPOINTER szConnStrIn,SQLSMALLINT cbConnStrIn,SQLPOINTER szConnStrOut,SQLSMALLINT cbConnStrOutMax,SQLSMALLINT * pcbConnStrOut,SQLCHAR waMode)3437 SQLBrowseConnect_Internal (SQLHDBC hdbc,
3438     SQLPOINTER szConnStrIn,
3439     SQLSMALLINT cbConnStrIn,
3440     SQLPOINTER szConnStrOut,
3441     SQLSMALLINT cbConnStrOutMax, SQLSMALLINT * pcbConnStrOut,
3442     SQLCHAR waMode)
3443 {
3444   CONN (pdbc, hdbc);
3445   ENVR (penv, NULL);
3446   char buf[1024];
3447   SWORD thread_safe;
3448   SWORD unload_safe;
3449   HPROC hproc = SQL_NULL_HPROC;
3450   void * _ConnStrIn = NULL;
3451   void * _ConnStrOut = NULL;
3452   void * connStrOut = szConnStrOut;
3453   void * connStrIn = szConnStrIn;
3454   CONV_DIRECT conv_direct = CD_NONE;
3455   DM_CONV *conv = NULL;
3456   IODBC_CHARSET drv_cp = CP_DEF;
3457 
3458   SQLRETURN retcode = SQL_SUCCESS;
3459   SQLRETURN setopterr = SQL_SUCCESS;
3460 
3461   /* check arguments */
3462   if ((cbConnStrIn < 0 && cbConnStrIn != SQL_NTS) || cbConnStrOutMax < 0)
3463     {
3464       PUSHSQLERR (pdbc->herr, en_S1090);
3465       return SQL_ERROR;
3466     }
3467 
3468   conv = (penv != SQL_NULL_HENV) ? &penv->conv : &((GENV_t *) pdbc->genv)->conv;
3469 
3470   if (pdbc->state == en_dbc_allocated)
3471     {
3472         PCONFIG pconfig;
3473         void *drv = NULL, *dsn = NULL;
3474 
3475         if (_iodbcdm_cfg_init_str (&pconfig, szConnStrIn, cbConnStrIn,
3476 			     waMode == 'W', conv) == -1)
3477           {
3478             PUSHSQLERR (pdbc->herr, en_HY001);
3479             return SQL_ERROR;
3480           }
3481         if (_iodbcdm_cfg_find (pconfig, "ODBC", "DRIVER") == 0)
3482           drv = pconfig->value;
3483         if (_iodbcdm_cfg_find (pconfig, "ODBC", "DSN") == 0)
3484           dsn = pconfig->value;
3485 
3486         if (_iodbcdm_cfg_find (pconfig, "ODBC", "DriverUnicodeType") == 0)
3487           {
3488             if (STRCASEEQ(pconfig->value, "1") || STRCASEEQ(pconfig->value, "utf16"))
3489               drv_cp = CP_UTF16;
3490             else if (STRCASEEQ(pconfig->value, "2") || STRCASEEQ(pconfig->value, "utf8"))
3491               drv_cp = CP_UTF8;
3492             else if (STRCASEEQ(pconfig->value, "0") || STRCASEEQ(pconfig->value, "ucs4"))
3493               drv_cp = CP_UCS4;
3494 
3495             DPRINTF ((stderr,
3496              "DEBUG: SQLBrowseConnect DriverUnicodeType=%s\n",
3497                 drv_cp==CP_UCS4?"UCS4":(drv_cp==CP_UTF16?"UTF16":"UTF8")));
3498           }
3499 
3500         if (dsn == NULL || ((char*)dsn)[0] == '\0')
3501           dsn = (void *) "default";
3502         else
3503           /* if you want tracing, you must use a DSN */
3504           {
3505 	    if (_iodbcdm_con_settracing (pdbc, (SQLCHAR *) dsn, SQL_NTS, waMode) == SQL_ERROR)
3506 	      {
3507                 _iodbcdm_cfg_done (pconfig);
3508 	        return SQL_ERROR;
3509 	      }
3510 	  }
3511 
3512         /*
3513          *  Check whether driver is thread safe
3514          */
3515         thread_safe = 1;		/* Assume driver is thread safe */
3516 
3517         SQLSetConfigMode (ODBC_BOTH_DSN);
3518         if ( SQLGetPrivateProfileString ((char *) dsn, "ThreadManager", "",
3519 		buf, sizeof(buf), "odbc.ini") &&
3520             (STRCASEEQ (buf, "on") || STRCASEEQ (buf, "1")))
3521           {
3522             thread_safe = 0;	/* Driver needs a thread manager */
3523           }
3524 
3525         /*
3526          *  Check whether driver is unload safe
3527          */
3528         unload_safe = 0;		/* Assume driver is not unload safe */
3529 
3530         SQLSetConfigMode (ODBC_BOTH_DSN);
3531         if ( SQLGetPrivateProfileString ((char *) dsn, "ThreadManager", "",
3532 		buf, sizeof(buf), "odbc.ini") &&
3533             (STRCASEEQ (buf, "on") || STRCASEEQ (buf, "1")))
3534           {
3535             unload_safe = 1;
3536           }
3537 
3538         /*
3539          *  Get the name of the driver module and load it
3540          */
3541         if (drv == NULL || *(char*)drv == '\0')
3542           {
3543             SQLSetConfigMode (ODBC_BOTH_DSN);
3544             if ( SQLGetPrivateProfileString ((char *) dsn, "Driver", "",
3545 		buf, sizeof(buf), "odbc.ini") != 0)
3546               {
3547                 drv = buf;
3548               }
3549           }
3550 
3551       if (drv == NULL)
3552 	{
3553 	  PUSHSQLERR (pdbc->herr, en_IM002);
3554           _iodbcdm_cfg_done (pconfig);
3555 	  return SQL_ERROR;
3556 	}
3557 
3558       retcode = _iodbcdm_driverload (dsn, (char *) drv, pdbc, thread_safe,
3559 		unload_safe, drv_cp, waMode);
3560       _iodbcdm_cfg_done (pconfig);
3561 
3562       switch (retcode)
3563 	{
3564 	case SQL_SUCCESS:
3565 	  break;
3566 
3567 	case SQL_SUCCESS_WITH_INFO:
3568 #if 0
3569 	  /*
3570 	   *  Unsuccessful in calling driver's SQLSetConnectOption() to set
3571 	   *  login timeout.
3572 	   */
3573 	  setopterr = SQL_ERROR;
3574 #endif
3575 	  break;
3576 
3577 	default:
3578           return retcode;
3579 	}
3580     }
3581   else if (pdbc->state != en_dbc_needdata)
3582     {
3583       PUSHSQLERR (pdbc->herr, en_08002);
3584       return SQL_ERROR;
3585     }
3586 
3587   penv = (ENV_t *) pdbc->henv;
3588   conv = &pdbc->conv;
3589 
3590   if (penv->unicode_driver && waMode != 'W')
3591     conv_direct = CD_A2W;
3592   else if (!penv->unicode_driver && waMode == 'W')
3593     conv_direct = CD_W2A;
3594   else if (waMode == 'W' && conv->dm_cp!=conv->drv_cp)
3595     conv_direct = CD_W2W;
3596 
3597   if (conv_direct != CD_NONE)
3598     {
3599       if ((_ConnStrOut = malloc((cbConnStrOutMax + 1)* WCHAR_MAXSIZE)) == NULL)
3600 	{
3601           PUSHSQLERR (pdbc->herr, en_HY001);
3602 	  return SQL_ERROR;
3603         }
3604       _ConnStrIn = conv_text_m2d (conv, szConnStrIn, SQL_NTS, conv_direct);
3605 
3606       connStrIn = _ConnStrIn;
3607       cbConnStrIn = SQL_NTS;
3608       connStrOut = _ConnStrOut;
3609     }
3610 
3611   ODBC_UNLOCK ();
3612   CALL_UDRIVER(hdbc, pdbc, retcode, hproc, penv->unicode_driver,
3613     en_BrowseConnect, (
3614        pdbc->dhdbc,
3615        connStrIn,
3616        cbConnStrIn,
3617        connStrOut,
3618        cbConnStrOutMax,
3619        pcbConnStrOut));
3620   ODBC_LOCK ();
3621 
3622   MEM_FREE(_ConnStrIn);
3623 
3624   if (hproc == SQL_NULL_HPROC)
3625     {
3626       MEM_FREE(_ConnStrOut);
3627       _iodbcdm_driverunload (pdbc, 3);
3628       pdbc->state = en_dbc_allocated;
3629       PUSHSQLERR (pdbc->herr, en_IM001);
3630       return SQL_ERROR;
3631     }
3632 
3633   if (szConnStrOut && SQL_SUCCEEDED (retcode) && conv_direct != CD_NONE)
3634     {
3635       if (conv_direct == CD_A2W)
3636         {
3637         /* ansi<=unicode*/
3638           dm_StrCopyOut2_W2A_d2m (conv, connStrOut, (SQLCHAR *) szConnStrOut,
3639 		cbConnStrOutMax, NULL, NULL);
3640         }
3641       else if (conv_direct == CD_W2A)
3642         {
3643         /* unicode<=ansi*/
3644           dm_StrCopyOut2_A2W_d2m (conv, (SQLCHAR *) connStrOut, szConnStrOut,
3645 		cbConnStrOutMax * DM_WCHARSIZE(conv), NULL, NULL);
3646         }
3647       else if (conv_direct == CD_W2W)
3648         {
3649         /* unicode<=unicode*/
3650           dm_StrCopyOut2_W2W_d2m (conv, connStrOut, szConnStrOut,
3651 		cbConnStrOutMax * DM_WCHARSIZE(conv), NULL, NULL);
3652         }
3653     }
3654 
3655   MEM_FREE(_ConnStrOut);
3656 
3657   switch (retcode)
3658     {
3659     case SQL_SUCCESS:
3660     case SQL_SUCCESS_WITH_INFO:
3661       pdbc->state = en_dbc_connected;
3662       setopterr |= _iodbcdm_dbcdelayset (pdbc, waMode);
3663       if (setopterr != SQL_SUCCESS)
3664 	{
3665 	  retcode = SQL_SUCCESS_WITH_INFO;
3666 	}
3667       break;
3668 
3669     case SQL_NEED_DATA:
3670       pdbc->state = en_dbc_needdata;
3671       break;
3672 
3673     case SQL_ERROR:
3674       pdbc->state = en_dbc_allocated;
3675       /* but the driver will not unloaded
3676        * to allow application retrieve err
3677        * message from driver
3678        */
3679       break;
3680 
3681     default:
3682       break;
3683     }
3684 
3685   return retcode;
3686 }
3687 
3688 
3689 SQLRETURN SQL_API
SQLBrowseConnect(SQLHDBC hdbc,SQLCHAR * szConnStrIn,SQLSMALLINT cbConnStrIn,SQLCHAR * szConnStrOut,SQLSMALLINT cbConnStrOutMax,SQLSMALLINT * pcbConnStrOut)3690 SQLBrowseConnect (SQLHDBC hdbc,
3691     SQLCHAR * szConnStrIn,
3692     SQLSMALLINT cbConnStrIn,
3693     SQLCHAR * szConnStrOut,
3694     SQLSMALLINT cbConnStrOutMax,
3695     SQLSMALLINT * pcbConnStrOut)
3696 {
3697   ENTER_HDBC (hdbc, 1,
3698     trace_SQLBrowseConnect (TRACE_ENTER,
3699       	hdbc,
3700 	szConnStrIn, cbConnStrIn,
3701 	szConnStrOut, cbConnStrOutMax, pcbConnStrOut));
3702 
3703   retcode = SQLBrowseConnect_Internal (
3704   	hdbc,
3705 	szConnStrIn, cbConnStrIn,
3706 	szConnStrOut, cbConnStrOutMax, pcbConnStrOut,
3707 	'A');
3708 
3709   LEAVE_HDBC (hdbc, 1,
3710     trace_SQLBrowseConnect (TRACE_LEAVE,
3711       	hdbc,
3712 	szConnStrIn, cbConnStrIn,
3713 	szConnStrOut, cbConnStrOutMax, pcbConnStrOut));
3714 }
3715 
3716 
3717 SQLRETURN SQL_API
SQLBrowseConnectA(SQLHDBC hdbc,SQLCHAR * szConnStrIn,SQLSMALLINT cbConnStrIn,SQLCHAR * szConnStrOut,SQLSMALLINT cbConnStrOutMax,SQLSMALLINT * pcbConnStrOut)3718 SQLBrowseConnectA (SQLHDBC hdbc,
3719     SQLCHAR * szConnStrIn,
3720     SQLSMALLINT cbConnStrIn,
3721     SQLCHAR * szConnStrOut,
3722     SQLSMALLINT cbConnStrOutMax,
3723     SQLSMALLINT * pcbConnStrOut)
3724 {
3725   ENTER_HDBC (hdbc, 1,
3726     trace_SQLBrowseConnect (TRACE_ENTER,
3727       	hdbc,
3728 	szConnStrIn, cbConnStrIn,
3729 	szConnStrOut, cbConnStrOutMax, pcbConnStrOut));
3730 
3731   retcode = SQLBrowseConnect_Internal (
3732   	hdbc,
3733 	szConnStrIn, cbConnStrIn,
3734 	szConnStrOut, cbConnStrOutMax, pcbConnStrOut,
3735 	'A');
3736 
3737   LEAVE_HDBC (hdbc, 1,
3738     trace_SQLBrowseConnect (TRACE_LEAVE,
3739       	hdbc,
3740 	szConnStrIn, cbConnStrIn,
3741 	szConnStrOut, cbConnStrOutMax, pcbConnStrOut));
3742 }
3743 
3744 
3745 SQLRETURN SQL_API
SQLBrowseConnectW(SQLHDBC hdbc,SQLWCHAR * szConnStrIn,SQLSMALLINT cbConnStrIn,SQLWCHAR * szConnStrOut,SQLSMALLINT cbConnStrOutMax,SQLSMALLINT * pcbConnStrOut)3746 SQLBrowseConnectW (SQLHDBC hdbc,
3747     SQLWCHAR * szConnStrIn,
3748     SQLSMALLINT cbConnStrIn,
3749     SQLWCHAR * szConnStrOut,
3750     SQLSMALLINT cbConnStrOutMax,
3751     SQLSMALLINT * pcbConnStrOut)
3752 {
3753   ENTER_HDBC (hdbc, 1,
3754     trace_SQLBrowseConnectW (TRACE_ENTER,
3755       	hdbc,
3756 	szConnStrIn, cbConnStrIn,
3757 	szConnStrOut, cbConnStrOutMax, pcbConnStrOut));
3758 
3759   retcode = SQLBrowseConnect_Internal (
3760   	hdbc,
3761 	szConnStrIn, cbConnStrIn,
3762 	szConnStrOut, cbConnStrOutMax, pcbConnStrOut,
3763 	'W');
3764 
3765   LEAVE_HDBC (hdbc, 1,
3766     trace_SQLBrowseConnectW (TRACE_LEAVE,
3767       	hdbc,
3768 	szConnStrIn, cbConnStrIn,
3769 	szConnStrOut, cbConnStrOutMax, pcbConnStrOut));
3770 }
3771 
3772 
3773 static SQLRETURN
SQLDisconnect_Internal(SQLHDBC hdbc)3774 SQLDisconnect_Internal (SQLHDBC hdbc)
3775 {
3776   CONN (pdbc, hdbc);
3777 #if (ODBCVER >= 0x300)
3778   GENV (genv, pdbc->genv);
3779 #endif
3780   STMT (pstmt, NULL);
3781 
3782   /* check hdbc state */
3783   if (pdbc->state == en_dbc_allocated)
3784     {
3785       PUSHSQLERR (pdbc->herr, en_08003);
3786       return SQL_ERROR;
3787     }
3788 
3789   /* check stmt(s) state */
3790   for (pstmt = (STMT_t *) pdbc->hstmt;
3791       pstmt != NULL;
3792       pstmt = (STMT_t *) pstmt->next)
3793     {
3794       if (pstmt->state >= en_stmt_needdata
3795 	  || pstmt->asyn_on != en_NullProc)
3796 	/* In this case one need to call
3797 	 * SQLCancel() first */
3798 	{
3799           PUSHSQLERR (pdbc->herr, en_S1010);
3800 	  return SQL_ERROR;
3801 	}
3802     }
3803 
3804 #if (ODBCVER >= 0x300)
3805   /*
3806    * Try to return the connected connection to the pool if
3807    * - connection was taken from the pool
3808    * - pooling is enabled and CPTimeout > 0
3809    */
3810   if ((pdbc->state == en_dbc_connected || pdbc->state == en_dbc_hstmt)
3811       && (pdbc->cp_pdbc != NULL ||
3812            (genv->connection_pooling != SQL_CP_OFF && pdbc->cp_timeout > 0)))
3813     {
3814       if (_iodbcdm_pool_put_conn (pdbc) == 0)
3815         {
3816           _iodbcdm_finish_disconnect (pdbc, FALSE);
3817           return SQL_SUCCESS;
3818         }
3819     }
3820 #endif /* (ODBCVER >= 0x300) */
3821 
3822   return _iodbcdm_finish_disconnect (pdbc, TRUE);
3823 }
3824 
3825 
3826 SQLRETURN SQL_API
SQLDisconnect(SQLHDBC hdbc)3827 SQLDisconnect (SQLHDBC hdbc)
3828 {
3829   ENTER_HDBC (hdbc, 1,
3830     trace_SQLDisconnect (TRACE_ENTER, hdbc));
3831 
3832   retcode = SQLDisconnect_Internal (hdbc);
3833 
3834   LEAVE_HDBC (hdbc, 1,
3835     trace_SQLDisconnect (TRACE_LEAVE, hdbc));
3836 }
3837 
3838 
3839 SQLRETURN SQL_API
SQLNativeSql_Internal(SQLHDBC hdbc,SQLPOINTER szSqlStrIn,SQLINTEGER cbSqlStrIn,SQLPOINTER szSqlStr,SQLINTEGER cbSqlStrMax,SQLINTEGER * pcbSqlStr,SQLCHAR waMode)3840 SQLNativeSql_Internal (SQLHDBC hdbc,
3841     SQLPOINTER szSqlStrIn,
3842     SQLINTEGER cbSqlStrIn,
3843     SQLPOINTER szSqlStr,
3844     SQLINTEGER cbSqlStrMax,
3845     SQLINTEGER * pcbSqlStr,
3846     SQLCHAR waMode)
3847 {
3848   CONN (pdbc, hdbc);
3849   ENVR (penv, pdbc->henv);
3850   sqlstcode_t sqlstat = en_00000;
3851   SQLRETURN retcode = SQL_SUCCESS;
3852   HPROC hproc = SQL_NULL_HPROC;
3853   void * _SqlStrIn = NULL;
3854   void * _SqlStr = NULL;
3855   void * sqlStr = szSqlStr;
3856   CONV_DIRECT conv_direct = CD_NONE;
3857   DM_CONV *conv = &pdbc->conv;
3858 
3859   /* check argument */
3860   if (szSqlStrIn == NULL)
3861     {
3862       sqlstat = en_S1009;
3863     }
3864   else if (cbSqlStrIn < 0 && cbSqlStrIn != SQL_NTS)
3865     {
3866       sqlstat = en_S1090;
3867     }
3868 
3869   if (sqlstat != en_00000)
3870     {
3871       PUSHSQLERR (pdbc->herr, sqlstat);
3872       return SQL_ERROR;
3873     }
3874 
3875   /* check state */
3876   if (pdbc->state <= en_dbc_needdata)
3877     {
3878       PUSHSQLERR (pdbc->herr, en_08003);
3879       return SQL_ERROR;
3880     }
3881 
3882   if (penv->unicode_driver && waMode != 'W')
3883     conv_direct = CD_A2W;
3884   else if (!penv->unicode_driver && waMode == 'W')
3885     conv_direct = CD_W2A;
3886   else if (waMode == 'W' && conv->dm_cp!=conv->drv_cp)
3887     conv_direct = CD_W2W;
3888 
3889   if (conv_direct != CD_NONE)
3890     {
3891       if ((_SqlStr = malloc((cbSqlStrMax + 1) * WCHAR_MAXSIZE)) == NULL)
3892         {
3893           PUSHSQLERR (pdbc->herr, en_HY001);
3894 	  return SQL_ERROR;
3895         }
3896       _SqlStrIn = conv_text_m2d (conv, szSqlStrIn, SQL_NTS, conv_direct);
3897 
3898       szSqlStrIn = _SqlStrIn;
3899       cbSqlStrIn = SQL_NTS;
3900       sqlStr = _SqlStr;
3901     }
3902 
3903   /* call driver */
3904   CALL_UDRIVER(hdbc, pdbc, retcode, hproc, penv->unicode_driver,
3905     en_NativeSql, (
3906        pdbc->dhdbc,
3907        szSqlStrIn,
3908        cbSqlStrIn,
3909        sqlStr,
3910        cbSqlStrMax,
3911        pcbSqlStr));
3912 
3913   MEM_FREE(_SqlStrIn);
3914 
3915   if (hproc == SQL_NULL_HPROC)
3916     {
3917       MEM_FREE(_SqlStr);
3918       PUSHSQLERR (pdbc->herr, en_IM001);
3919 
3920       return SQL_ERROR;
3921     }
3922 
3923   if (szSqlStr && conv_direct != CD_NONE
3924       && SQL_SUCCEEDED (retcode))
3925     {
3926       if (conv_direct == CD_A2W)
3927         {
3928         /* ansi<=unicode*/
3929           dm_StrCopyOut2_W2A_d2m (conv, sqlStr, (SQLCHAR *) szSqlStr,
3930 		cbSqlStrMax, NULL, NULL);
3931         }
3932       else if (conv_direct == CD_W2A)
3933         {
3934         /* unicode<=ansi*/
3935           dm_StrCopyOut2_A2W_d2m (conv, (SQLCHAR *) sqlStr, szSqlStr,
3936 		cbSqlStrMax * DM_WCHARSIZE(conv), NULL, NULL);
3937         }
3938       else if (conv_direct == CD_W2W)
3939         {
3940         /* unicode<=unicode*/
3941           dm_StrCopyOut2_W2W_d2m (conv, sqlStr, szSqlStr,
3942 		cbSqlStrMax * DM_WCHARSIZE(conv), NULL, NULL);
3943         }
3944     }
3945 
3946   MEM_FREE(_SqlStr);
3947 
3948   return retcode;
3949 }
3950 
3951 
3952 SQLRETURN SQL_API
SQLNativeSql(SQLHDBC hdbc,SQLCHAR * szSqlStrIn,SQLINTEGER cbSqlStrIn,SQLCHAR * szSqlStr,SQLINTEGER cbSqlStrMax,SQLINTEGER * pcbSqlStr)3953 SQLNativeSql (
3954     SQLHDBC hdbc,
3955     SQLCHAR * szSqlStrIn,
3956     SQLINTEGER cbSqlStrIn,
3957     SQLCHAR * szSqlStr,
3958     SQLINTEGER cbSqlStrMax,
3959     SQLINTEGER * pcbSqlStr)
3960 {
3961   ENTER_HDBC (hdbc, 0,
3962     trace_SQLNativeSql (TRACE_ENTER,
3963     	hdbc,
3964 	szSqlStrIn, cbSqlStrIn,
3965 	szSqlStr, cbSqlStrMax, pcbSqlStr));
3966 
3967   retcode = SQLNativeSql_Internal (
3968   	hdbc,
3969 	szSqlStrIn, cbSqlStrIn,
3970 	szSqlStr, cbSqlStrMax, pcbSqlStr,
3971 	'A');
3972 
3973   LEAVE_HDBC (hdbc, 0,
3974     trace_SQLNativeSql (TRACE_LEAVE,
3975     	hdbc,
3976 	szSqlStrIn, cbSqlStrIn,
3977 	szSqlStr, cbSqlStrMax, pcbSqlStr));
3978 }
3979 
3980 
3981 SQLRETURN SQL_API
SQLNativeSqlA(SQLHDBC hdbc,SQLCHAR * szSqlStrIn,SQLINTEGER cbSqlStrIn,SQLCHAR * szSqlStr,SQLINTEGER cbSqlStrMax,SQLINTEGER * pcbSqlStr)3982 SQLNativeSqlA (
3983     SQLHDBC hdbc,
3984     SQLCHAR * szSqlStrIn,
3985     SQLINTEGER cbSqlStrIn,
3986     SQLCHAR * szSqlStr,
3987     SQLINTEGER cbSqlStrMax,
3988     SQLINTEGER * pcbSqlStr)
3989 {
3990   ENTER_HDBC (hdbc, 0,
3991     trace_SQLNativeSql (TRACE_ENTER,
3992     	hdbc,
3993 	szSqlStrIn, cbSqlStrIn,
3994 	szSqlStr, cbSqlStrMax, pcbSqlStr));
3995 
3996   retcode = SQLNativeSql_Internal(
3997   	hdbc,
3998 	szSqlStrIn, cbSqlStrIn,
3999 	szSqlStr, cbSqlStrMax, pcbSqlStr,
4000 	'A');
4001 
4002   LEAVE_HDBC (hdbc, 0,
4003     trace_SQLNativeSql (TRACE_LEAVE,
4004     	hdbc,
4005 	szSqlStrIn, cbSqlStrIn,
4006 	szSqlStr, cbSqlStrMax, pcbSqlStr));
4007 }
4008 
4009 
4010 SQLRETURN SQL_API
SQLNativeSqlW(SQLHDBC hdbc,SQLWCHAR * szSqlStrIn,SQLINTEGER cbSqlStrIn,SQLWCHAR * szSqlStr,SQLINTEGER cbSqlStrMax,SQLINTEGER * pcbSqlStr)4011 SQLNativeSqlW (
4012     SQLHDBC hdbc,
4013     SQLWCHAR * szSqlStrIn,
4014     SQLINTEGER cbSqlStrIn,
4015     SQLWCHAR * szSqlStr,
4016     SQLINTEGER cbSqlStrMax,
4017     SQLINTEGER * pcbSqlStr)
4018 {
4019   ENTER_HDBC (hdbc, 0,
4020     trace_SQLNativeSqlW (TRACE_ENTER,
4021     	hdbc,
4022 	szSqlStrIn, cbSqlStrIn,
4023 	szSqlStr, cbSqlStrMax, pcbSqlStr));
4024 
4025   retcode = SQLNativeSql_Internal(
4026   	hdbc,
4027 	szSqlStrIn, cbSqlStrIn,
4028 	szSqlStr, cbSqlStrMax, pcbSqlStr,
4029 	'W');
4030 
4031   LEAVE_HDBC (hdbc, 0,
4032     trace_SQLNativeSqlW (TRACE_LEAVE,
4033     	hdbc,
4034 	szSqlStrIn, cbSqlStrIn,
4035 	szSqlStr, cbSqlStrMax, pcbSqlStr));
4036 }
4037