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