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