6  *  Connect (load) driver 
   8  *  The iODBC driver manager. 
  10  *  Copyright (C) 1995 by Ke Jin <kejin@empress.com>  
  12  *  This library is free software; you can redistribute it and/or 
  13  *  modify it under the terms of the GNU Library General Public 
  14  *  License as published by the Free Software Foundation; either 
  15  *  version 2 of the License, or (at your option) any later version. 
  17  *  This library is distributed in the hope that it will be useful, 
  18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
  19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
  20  *  Library General Public License for more details. 
  22  *  You should have received a copy of the GNU Library General Public 
  23  *  License along with this library; if not, write to the Free 
  24  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  41 extern  char*   _iodbcdm_getkeyvalbydsn(); 
  42 extern  char*   _iodbcdm_getkeyvalinstr(); 
  43 extern  RETCODE 
_iodbcdm_driverunload(); 
  46  *   Following id string is a copyright mark. Removing(i.e. use  
  47  *   souce code of this package without it or make it not appear  
  48  *   in the final object file) or modifing it without permission  
  49  *   from original author(kejin@empress.com) are copyright  
  53         = "@(#)iODBC driver manager 2.5, Copyright(c) 1995 by Ke Jin"; 
  55 /* - Load driver share library( or increase its reference count  
  56  *   if it has already been loaded by another active connection) 
  57  * - Call driver's SQLAllocEnv() (for the first reference only) 
  58  * - Call driver's SQLAllocConnect() 
  59  * - Call driver's SQLSetConnectOption() (set login time out) 
  60  * - Increase the bookkeeping reference count 
  67   DBC_t FAR 
*pdbc 
= (DBC_t FAR 
*) hdbc
; 
  69   ENV_t FAR 
*penv 
= NULL
; 
  72   RETCODE retcode 
= SQL_SUCCESS
; 
  73   int sqlstat 
= en_00000
; 
  75   if (path 
== NULL 
|| path
[0] == '\0') 
  77       PUSHSQLERR (pdbc
->herr
, en_IM002
); 
  82   if (hdbc 
== SQL_NULL_HDBC 
|| pdbc
->genv 
== SQL_NULL_HENV
) 
  84       return SQL_INVALID_HANDLE
; 
  87   genv 
= (GENV_t FAR 
*) pdbc
->genv
; 
  89   /* This will either load the driver dll or increase its reference count */ 
  90   hdll 
= _iodbcdm_dllopen ((char FAR 
*) path
); 
  92   if (hdll 
== SQL_NULL_HDLL
) 
  94       PUSHSYSERR (pdbc
->herr
, _iodbcdm_dllerror ()); 
  95       PUSHSQLERR (pdbc
->herr
, en_IM003
); 
  99   penv 
= (ENV_t FAR 
*) (pdbc
->henv
); 
 103       if (penv
->hdll 
!= hdll
) 
 105           _iodbcdm_driverunload (hdbc
); 
 110            * this will not unload the driver but only decrease its internal 
 113           _iodbcdm_dllclose (hdll
); 
 120        * find out whether this dll has already been loaded on another  
 123       for (penv 
= (ENV_t FAR 
*) genv
->henv
;  
 125           penv 
= (ENV_t FAR 
*) penv
->next
) 
 127           if (penv
->hdll 
== hdll
) 
 130                * this will not unload the driver but only decrease its internal 
 133               _iodbcdm_dllclose (hdll
); 
 139         /* no connection attaching with this dll */ 
 143           /* create a new dll env instance */ 
 144           penv 
= (ENV_t FAR 
*) MEM_ALLOC (sizeof (ENV_t
)); 
 148               _iodbcdm_dllclose (hdll
); 
 150               PUSHSQLERR (pdbc
->herr
, en_S1001
); 
 155           for (i 
= 0; i 
< SQL_EXT_API_LAST 
+ 1; i
++) 
 157               (penv
->dllproc_tab
)[i
] = SQL_NULL_HPROC
; 
 163           /* call driver's SQLAllocHandle() or SQLAllocEnv() */ 
 165 #if (ODBCVER >= 0x0300) 
 166           hproc 
= _iodbcdm_getproc (hdbc
, en_AllocHandle
); 
 170               CALL_DRIVER (hdbc
, retcode
, hproc
, en_AllocHandle
, 
 171                   (SQL_HANDLE_ENV
, SQL_NULL_HANDLE
, &(penv
->dhenv
))) 
 173           else                  /* try driver's SQLAllocEnv() */ 
 176               hproc 
= _iodbcdm_getproc (hdbc
, en_AllocEnv
); 
 178               if (hproc 
== SQL_NULL_HPROC
) 
 184                   CALL_DRIVER (hdbc
, retcode
, hproc
, 
 185                       en_AllocEnv
, (&(penv
->dhenv
))) 
 189           if (retcode 
== SQL_ERROR
) 
 194           if (sqlstat 
!= en_00000
) 
 196               _iodbcdm_dllclose (hdll
); 
 198               PUSHSQLERR (pdbc
->herr
, en_IM004
); 
 203           /* insert into dll env list */ 
 204           penv
->next 
= (ENV_t FAR 
*) genv
->henv
; 
 207           /* initiate this new env entry */ 
 208           penv
->refcount 
= 0;   /* we will increase it after 
 209                                  * driver's SQLAllocConnect() 
 216       if (pdbc
->dhdbc 
== SQL_NULL_HDBC
) 
 219 #if (ODBCVER >= 0x0300) 
 220           hproc 
= _iodbcdm_getproc (hdbc
, en_AllocHandle
); 
 224               CALL_DRIVER (hdbc
, retcode
, hproc
, en_AllocHandle
, 
 225                   (SQL_HANDLE_DBC
, penv
->dhenv
, &(pdbc
->dhdbc
))) 
 231               hproc 
= _iodbcdm_getproc (hdbc
, en_AllocConnect
); 
 233               if (hproc 
== SQL_NULL_HPROC
) 
 239                   CALL_DRIVER (hdbc
, retcode
, hproc
, 
 240                       en_AllocConnect
, (penv
->dhenv
, &(pdbc
->dhdbc
))) 
 244           if (retcode 
== SQL_ERROR
) 
 249           if (sqlstat 
!= en_00000
) 
 251               _iodbcdm_driverunload (hdbc
); 
 253               pdbc
->dhdbc 
= SQL_NULL_HDBC
; 
 254               PUSHSQLERR (pdbc
->herr
, en_IM005
); 
 261       penv
->refcount
++;         /* bookkeeping reference count on this driver */ 
 264   /* driver's login timeout option must been set before  
 265    * its SQLConnect() call */ 
 266   if (pdbc
->login_timeout 
!= 0UL) 
 268       hproc 
= _iodbcdm_getproc (hdbc
, en_SetConnectOption
); 
 270       if (hproc 
== SQL_NULL_HPROC
) 
 276           CALL_DRIVER (hdbc
, retcode
, hproc
, 
 277               en_SetConnectOption
, ( 
 280                   pdbc
->login_timeout
)) 
 282               if (retcode 
== SQL_ERROR
) 
 284               PUSHSQLERR (pdbc
->herr
, en_IM006
); 
 286               return SQL_SUCCESS_WITH_INFO
; 
 295 /* - Call driver's SQLFreeConnect() 
 296  * - Call driver's SQLFreeEnv() ( for the last reference only) 
 297  * - Unload the share library( or decrease its reference 
 298  *   count if it is not the last referenct ) 
 299  * - decrease bookkeeping reference count 
 300  * - state transition to allocated 
 303 _iodbcdm_driverunload (HDBC hdbc
) 
 305   DBC_t FAR 
*pdbc 
= (DBC_t FAR 
*) hdbc
; 
 310   RETCODE retcode 
= SQL_SUCCESS
; 
 312   if (hdbc 
== SQL_NULL_HDBC
) 
 314       return SQL_INVALID_HANDLE
; 
 317   /* no pointer check will be performed in this function */ 
 318   penv 
= (ENV_t FAR 
*) pdbc
->henv
; 
 319   genv 
= (GENV_t FAR 
*) pdbc
->genv
; 
 321   if (penv 
== NULL 
|| penv
->hdll 
== SQL_NULL_HDLL
) 
 326 #if (ODBCVER >= 0x0300) 
 327   hproc 
= _iodbcdm_getproc (hdbc
, en_FreeHandle
); 
 331       CALL_DRIVER (hdbc
, retcode
, hproc
, en_FreeHandle
, 
 332           (SQL_HANDLE_DBC
, pdbc
->dhdbc
)) 
 338       hproc 
= _iodbcdm_getproc (hdbc
, en_FreeConnect
); 
 340       if (hproc 
!= SQL_NULL_HPROC
) 
 342           CALL_DRIVER (hdbc
, retcode
, hproc
, 
 343               en_FreeConnect
, (pdbc
->dhdbc
)) 
 345               pdbc
->dhdbc 
= SQL_NULL_HDBC
; 
 352     /* no other connections still attaching with this driver */ 
 355 #if (ODBCVER >= 0x0300) 
 356       hproc 
= _iodbcdm_getproc (hdbc
, en_FreeHandle
); 
 360           CALL_DRIVER (hdbc
, retcode
, hproc
, en_FreeHandle
, 
 361               (SQL_HANDLE_ENV
, penv
->dhenv
)) 
 367           hproc 
= _iodbcdm_getproc (hdbc
, en_FreeEnv
); 
 369           if (hproc 
!= SQL_NULL_HPROC
) 
 371               CALL_DRIVER (hdbc
, retcode
, hproc
, en_FreeEnv
, 
 374                   penv
->dhenv 
= SQL_NULL_HENV
; 
 378       _iodbcdm_dllclose (penv
->hdll
); 
 380       penv
->hdll 
= SQL_NULL_HDLL
; 
 382       for (tpenv 
= (ENV_t FAR 
*) genv
->henv
; 
 384           tpenv 
= (ENV_t FAR 
*) penv
->next
) 
 388               genv
->henv 
= penv
->next
; 
 392           if (tpenv
->next 
== penv
) 
 394               tpenv
->next 
= penv
->next
; 
 402   pdbc
->henv 
= SQL_NULL_HENV
; 
 403   pdbc
->hstmt 
= SQL_NULL_HSTMT
; 
 404   /* pdbc->herr = SQL_NULL_HERR;  
 405      -- delay to DM's SQLFreeConnect() */ 
 406   pdbc
->dhdbc 
= SQL_NULL_HDBC
; 
 407   pdbc
->state 
= en_dbc_allocated
; 
 409   /* set connect options to default values */ 
 411         pdbc->access_mode       = SQL_MODE_DEFAULT; 
 412         pdbc->autocommit        = SQL_AUTOCOMMIT_DEFAULT; 
 413         pdbc->login_timeout     = 0UL; 
 415   pdbc
->odbc_cursors 
= SQL_CUR_DEFAULT
; 
 416   pdbc
->packet_size 
= 0UL; 
 417   pdbc
->quiet_mode 
= (UDWORD
) NULL
; 
 418   pdbc
->txn_isolation 
= SQL_TXN_READ_UNCOMMITTED
; 
 420   if (pdbc
->current_qualifier 
!= NULL
) 
 422       MEM_FREE (pdbc
->current_qualifier
); 
 423       pdbc
->current_qualifier 
= NULL
; 
 431 _iodbcdm_dbcdelayset (HDBC hdbc
) 
 433   DBC_t FAR 
*pdbc 
= (DBC_t FAR 
*) hdbc
; 
 436   RETCODE retcode 
= SQL_SUCCESS
; 
 441   hproc 
= _iodbcdm_getproc (hdbc
, en_SetConnectOption
); 
 443   if (hproc 
== SQL_NULL_HPROC
) 
 445       PUSHSQLERR (pdbc
->herr
, en_IM006
); 
 447       return SQL_SUCCESS_WITH_INFO
; 
 450   if (pdbc
->access_mode 
!= SQL_MODE_DEFAULT
) 
 452       CALL_DRIVER (hdbc
, ret
, hproc
, 
 453           en_SetConnectOption
, ( 
 460   if (pdbc
->autocommit 
!= SQL_AUTOCOMMIT_DEFAULT
) 
 462       CALL_DRIVER (hdbc
, ret
, hproc
, 
 463           en_SetConnectOption
, ( 
 471   if (pdbc
->current_qualifier 
!= NULL
) 
 473       CALL_DRIVER (hdbc
, ret
, hproc
, 
 474           en_SetConnectOption
, ( 
 476               SQL_CURRENT_QUALIFIER
, 
 477               pdbc
->current_qualifier
)) 
 482   if (pdbc
->packet_size 
!= 0UL) 
 484       CALL_DRIVER (hdbc
, ret
, hproc
, 
 485           en_SetConnectOption
, ( 
 493   if (pdbc
->quiet_mode 
!= (UDWORD
) NULL
) 
 495       CALL_DRIVER (hdbc
, ret
, hproc
, 
 496           en_SetConnectOption
, ( 
 504   if (pdbc
->txn_isolation 
!= SQL_TXN_READ_UNCOMMITTED
) 
 506       CALL_DRIVER (hdbc
, ret
, hproc
, 
 507           en_SetConnectOption
, ( 
 510               pdbc
->txn_isolation
)) 
 513   /* check error code for driver's SQLSetConnectOption() call */ 
 514   if (retcode 
!= SQL_SUCCESS 
&& retcode 
!= SQL_SUCCESS_WITH_INFO
) 
 516       PUSHSQLERR (pdbc
->herr
, en_IM006
); 
 521   /* get cursor behavior on transaction commit or rollback */ 
 522   hproc 
= _iodbcdm_getproc (hdbc
, en_GetInfo
); 
 524   if (hproc 
== SQL_NULL_HPROC
) 
 526       PUSHSQLERR (pdbc
->herr
, en_01000
); 
 531   CALL_DRIVER (hdbc
, ret
, hproc
, 
 534           SQL_CURSOR_COMMIT_BEHAVIOR
, 
 535           (PTR
) & (pdbc
->cb_commit
), 
 536           sizeof (pdbc
->cb_commit
), 
 541   CALL_DRIVER (hdbc
, ret
, hproc
, 
 544           SQL_CURSOR_ROLLBACK_BEHAVIOR
, 
 545           (PTR
) & (pdbc
->cb_rollback
), 
 546           sizeof (pdbc
->cb_rollback
), 
 551   if (retcode 
!= SQL_SUCCESS
 
 552       && retcode 
!= SQL_SUCCESS_WITH_INFO
) 
 562 _iodbcdm_settracing (HDBC hdbc
, char *dsn
, int dsnlen
) 
 566   RETCODE setopterr 
= SQL_SUCCESS
; 
 568   /* Get Driver's DLL path from specificed or default dsn section */ 
 569   ptr 
= _iodbcdm_getkeyvalbydsn (dsn
, dsnlen
, "TraceFile", 
 570       (char FAR 
*) buf
, sizeof (buf
)); 
 572   if (ptr 
== NULL 
|| ptr
[0] == '\0') 
 574       ptr 
= (char FAR 
*) (SQL_OPT_TRACE_FILE_DEFAULT
); 
 577   setopterr 
|= SQLSetConnectOption (hdbc
, SQL_OPT_TRACEFILE
, (UDWORD
) (ptr
)); 
 579   ptr 
= _iodbcdm_getkeyvalbydsn (dsn
, dsnlen
, "Trace", 
 580       (char FAR 
*) buf
, sizeof (buf
)); 
 584       UDWORD opt 
= (UDWORD
) (-1L); 
 586       if (STREQ (ptr
, "ON") 
 591           opt 
= SQL_OPT_TRACE_ON
; 
 594       if (STREQ (ptr
, "OFF") 
 595           || STREQ (ptr
, "Off") 
 596           || STREQ (ptr
, "off") 
 599           opt 
= SQL_OPT_TRACE_OFF
; 
 602       if (opt 
!= (UDWORD
) (-1L)) 
 604           setopterr 
|= SQLSetConnectOption (hdbc
, 
 620     UCHAR FAR 
* szAuthStr
, 
 623   DBC_t FAR 
*pdbc 
= (DBC_t FAR 
*) hdbc
; 
 624   RETCODE retcode 
= SQL_SUCCESS
; 
 625   RETCODE setopterr 
= SQL_SUCCESS
; 
 626   char driver
[1024] = {'\0'};   /* MS SDK Guide  
 633   if (hdbc 
== SQL_NULL_HDBC
) 
 635       return SQL_INVALID_HANDLE
; 
 638   /* check arguments */ 
 639   if ((cbDSN 
< 0 && cbDSN 
!= SQL_NTS
) 
 640       || (cbUID 
< 0 && cbUID 
!= SQL_NTS
) 
 641       || (cbAuthStr 
< 0 && cbAuthStr 
!= SQL_NTS
) 
 642       || (cbDSN 
> SQL_MAX_DSN_LENGTH
)) 
 644       PUSHSQLERR (pdbc
->herr
, en_S1090
); 
 649   if (szDSN 
== NULL 
|| cbDSN 
== 0) 
 651       PUSHSQLERR (pdbc
->herr
, en_IM002
); 
 657   if (pdbc
->state 
!= en_dbc_allocated
) 
 659       PUSHSQLERR (pdbc
->herr
, en_08002
); 
 664   setopterr 
|= _iodbcdm_settracing (hdbc
, 
 665       (char *) szDSN
, cbDSN
); 
 667   ptr 
= _iodbcdm_getkeyvalbydsn (szDSN
, cbDSN
, "Driver", 
 668       (char FAR 
*) driver
, sizeof (driver
)); 
 671     /* No specified or default dsn section or 
 672      * no driver specification in this dsn section */ 
 674       PUSHSQLERR (pdbc
->herr
, en_IM002
); 
 679   retcode 
= _iodbcdm_driverload (driver
, hdbc
); 
 686      case SQL_SUCCESS_WITH_INFO
: 
 687        setopterr 
= SQL_ERROR
; 
 688        /* unsuccessed in calling driver's  
 689         * SQLSetConnectOption() to set login 
 698   hproc 
= _iodbcdm_getproc (hdbc
, en_Connect
); 
 700   if (hproc 
== SQL_NULL_HPROC
) 
 702       _iodbcdm_driverunload (hdbc
); 
 704       PUSHSQLERR (pdbc
->herr
, en_IM001
); 
 709   CALL_DRIVER (hdbc
, retcode
, hproc
, en_Connect
, ( 
 713           szAuthStr
, cbAuthStr
)) 
 715   if (retcode 
!= SQL_SUCCESS
 
 716       && retcode 
!= SQL_SUCCESS_WITH_INFO
) 
 718       /* not unload driver for retrive error  
 719        * messge from driver */ 
 721                 _iodbcdm_driverunload( hdbc ); 
 727   /* state transition */ 
 728   pdbc
->state 
= en_dbc_connected
; 
 730   /* do delaid option setting */ 
 731   setopterr 
|= _iodbcdm_dbcdelayset (hdbc
); 
 733   if (setopterr 
!= SQL_SUCCESS
) 
 735       return SQL_SUCCESS_WITH_INFO
; 
 746     UCHAR FAR 
* szConnStrIn
, 
 748     UCHAR FAR 
* szConnStrOut
, 
 749     SWORD cbConnStrOutMax
, 
 750     SWORD FAR 
* pcbConnStrOut
, 
 751     UWORD fDriverCompletion
) 
 753   DBC_t FAR 
*pdbc 
= (DBC_t FAR 
*) hdbc
; 
 758   char dsnbuf
[SQL_MAX_DSN_LENGTH 
+ 1]; 
 759   UCHAR cnstr2drv
[1024]; 
 764   int sqlstat 
= en_00000
; 
 765   RETCODE retcode 
= SQL_SUCCESS
; 
 766   RETCODE setopterr 
= SQL_SUCCESS
; 
 768   if (hdbc 
== SQL_NULL_HDBC
) 
 770       return SQL_INVALID_HANDLE
; 
 773   /* check arguments */ 
 774   if ((cbConnStrIn 
< 0 && cbConnStrIn 
!= SQL_NTS
) 
 775       || cbConnStrOutMax 
< 0) 
 777       PUSHSQLERR (pdbc
->herr
, en_S1090
); 
 783   if (pdbc
->state 
!= en_dbc_allocated
) 
 785       PUSHSQLERR (pdbc
->herr
, en_08002
); 
 790   drv 
= _iodbcdm_getkeyvalinstr (szConnStrIn
, cbConnStrIn
, 
 791       "DRIVER", drvbuf
, sizeof (drvbuf
)); 
 793   dsn 
= _iodbcdm_getkeyvalinstr (szConnStrIn
, cbConnStrIn
, 
 794       "DSN", dsnbuf
, sizeof (dsnbuf
)); 
 796   switch (fDriverCompletion
) 
 798      case SQL_DRIVER_NOPROMPT
: 
 801      case SQL_DRIVER_COMPLETE
: 
 802      case SQL_DRIVER_COMPLETE_REQUIRED
: 
 803        if (dsn 
!= NULL 
|| drv 
!= NULL
) 
 807        /* fall to next case */ 
 808      case SQL_DRIVER_PROMPT
: 
 809        /* Get data source dialog box function from 
 810         * current executable */ 
 811        hdll 
= _iodbcdm_dllopen ((char FAR 
*) NULL
); 
 812        dialproc 
= _iodbcdm_dllproc (hdll
, 
 813            "_iodbcdm_drvconn_dialbox"); 
 815        if (dialproc 
== SQL_NULL_HPROC
) 
 822            hwnd
,                /* window or display handle */ 
 823            dsnbuf
,              /* input/output dsn buf */ 
 824            sizeof (dsnbuf
),     /* buf size */ 
 825            &sqlstat
);           /* error code */ 
 827        if (retcode 
!= SQL_SUCCESS
) 
 832        if (cbConnStrIn 
== SQL_NTS
) 
 834            cbConnStrIn 
= STRLEN (szConnStrIn
); 
 844        if (cbConnStrIn 
> sizeof (cnstr2drv
) 
 845            - STRLEN (dsn
) - STRLEN ("DSN=;") - 1) 
 847            sqlstat 
= en_S1001
;  /* a lazy way to avoid 
 848                                  * using heap memory */ 
 852        sprintf ((char*)cnstr2drv
, "DSN=%s;", dsn
); 
 853        cbConnStrIn 
+= STRLEN (cnstr2drv
); 
 854        STRNCAT (cnstr2drv
, szConnStrIn
, cbConnStrIn
); 
 855        szConnStrIn 
= cnstr2drv
; 
 863   if (sqlstat 
!= en_00000
) 
 865       PUSHSQLERR (pdbc
->herr
, sqlstat
); 
 870   if (dsn 
== NULL 
|| dsn
[0] == '\0') 
 875     /* if you want tracing, you must use a DSN */ 
 877       setopterr 
|= _iodbcdm_settracing (hdbc
, 
 878           (char *) dsn
, SQL_NTS
); 
 881   if (drv 
== NULL 
|| drv
[0] == '\0') 
 883       drv 
= _iodbcdm_getkeyvalbydsn (dsn
, SQL_NTS
, "Driver", 
 884           drvbuf
, sizeof (drvbuf
)); 
 889       PUSHSQLERR (pdbc
->herr
, en_IM002
); 
 894   retcode 
= _iodbcdm_driverload (drv
, hdbc
); 
 901      case SQL_SUCCESS_WITH_INFO
: 
 902        setopterr 
= SQL_ERROR
; 
 903        /* unsuccessed in calling driver's  
 904         * SQLSetConnectOption() to set login 
 913   hproc 
= _iodbcdm_getproc (hdbc
, en_DriverConnect
); 
 915   if (hproc 
== SQL_NULL_HPROC
) 
 917       _iodbcdm_driverunload (hdbc
); 
 919       PUSHSQLERR (pdbc
->herr
, en_IM001
); 
 924   CALL_DRIVER (hdbc
, retcode
, hproc
, en_DriverConnect
, ( 
 926           szConnStrIn
, cbConnStrIn
, 
 927           szConnStrOut
, cbConnStrOutMax
, 
 928           pcbConnStrOut
, fDriverCompletion
)) 
 930   if (retcode 
!= SQL_SUCCESS 
&& retcode 
!= SQL_SUCCESS_WITH_INFO
) 
 932       /* don't unload driver here for retrive  
 933        * error message from driver */ 
 935                 _iodbcdm_driverunload( hdbc ); 
 941   /* state transition */ 
 942   pdbc
->state 
= en_dbc_connected
; 
 944   /* do delaid option setting */ 
 945   setopterr 
|= _iodbcdm_dbcdelayset (hdbc
); 
 947   if (setopterr 
!= SQL_SUCCESS
) 
 949       return SQL_SUCCESS_WITH_INFO
; 
 959     UCHAR FAR 
* szConnStrIn
, 
 961     UCHAR FAR 
* szConnStrOut
, 
 962     SWORD cbConnStrOutMax
, 
 963     SWORD FAR 
* pcbConnStrOut
) 
 965   DBC_t FAR 
*pdbc 
= (DBC_t FAR 
*) hdbc
; 
 969   char dsnbuf
[SQL_MAX_DSN_LENGTH 
+ 1]; 
 973   RETCODE retcode 
= SQL_SUCCESS
; 
 974   RETCODE setopterr 
= SQL_SUCCESS
; 
 976   if (hdbc 
== SQL_NULL_HDBC
) 
 978       return SQL_INVALID_HANDLE
; 
 981   /* check arguments */ 
 982   if ((cbConnStrIn 
< 0 && cbConnStrIn 
!= SQL_NTS
) || cbConnStrOutMax 
< 0) 
 984       PUSHSQLERR (pdbc
->herr
, en_S1090
); 
 989   if (pdbc
->state 
== en_dbc_allocated
) 
 991       drv 
= _iodbcdm_getkeyvalinstr (szConnStrIn
, cbConnStrIn
, 
 992           "DRIVER", drvbuf
, sizeof (drvbuf
)); 
 994       dsn 
= _iodbcdm_getkeyvalinstr (szConnStrIn
, cbConnStrIn
, 
 995           "DSN", dsnbuf
, sizeof (dsnbuf
)); 
 997       if (dsn 
== NULL 
|| dsn
[0] == '\0') 
1002         /* if you want tracing, you must use a DSN */ 
1004           setopterr 
|= _iodbcdm_settracing (hdbc
, 
1005               (char *) dsn
, SQL_NTS
); 
1008       if (drv 
== NULL 
|| drv
[0] == '\0') 
1010           drv 
= _iodbcdm_getkeyvalbydsn (dsn
, SQL_NTS
, "Driver", 
1011               drvbuf
, sizeof (drvbuf
)); 
1016           PUSHSQLERR (pdbc
->herr
, en_IM002
); 
1021       retcode 
= _iodbcdm_driverload (drv
, hdbc
); 
1028          case SQL_SUCCESS_WITH_INFO
: 
1029            setopterr 
= SQL_ERROR
; 
1030            /* unsuccessed in calling driver's  
1031             * SQLSetConnectOption() to set login 
1040   else if (pdbc
->state 
!= en_dbc_needdata
) 
1042       PUSHSQLERR (pdbc
->herr
, en_08002
); 
1047   hproc 
= _iodbcdm_getproc (hdbc
, en_BrowseConnect
); 
1049   if (hproc 
== SQL_NULL_HPROC
) 
1051       _iodbcdm_driverunload (hdbc
); 
1053       pdbc
->state 
= en_dbc_allocated
; 
1055       PUSHSQLERR (pdbc
->herr
, en_IM001
); 
1060   CALL_DRIVER (hdbc
, retcode
, hproc
, en_BrowseConnect
, ( 
1062           szConnStrIn
, cbConnStrIn
,  
1063           szConnStrOut
, cbConnStrOutMax
, 
1069      case SQL_SUCCESS_WITH_INFO
: 
1070        pdbc
->state 
= en_dbc_connected
; 
1071        setopterr 
|= _iodbcdm_dbcdelayset (hdbc
); 
1072        if (setopterr 
!= SQL_SUCCESS
) 
1074            retcode 
= SQL_SUCCESS_WITH_INFO
; 
1079        pdbc
->state 
= en_dbc_needdata
; 
1083        pdbc
->state 
= en_dbc_allocated
; 
1084        /* but the driver will not unloaded  
1085         * to allow application retrive err 
1086         * message from driver  
1099 SQLDisconnect (HDBC hdbc
) 
1101   DBC_t FAR 
*pdbc 
= (DBC_t 
*) hdbc
; 
1106   int sqlstat 
= en_00000
; 
1108   if (hdbc 
== SQL_NULL_HDBC
) 
1110       return SQL_INVALID_HANDLE
; 
1113   /* check hdbc state */ 
1114   if (pdbc
->state 
== en_dbc_allocated
) 
1119   /* check stmt(s) state */ 
1120   for (pstmt 
= (STMT_t FAR 
*) pdbc
->hstmt
; 
1121       pstmt 
!= NULL 
&& sqlstat 
== en_00000
; 
1122       pstmt 
= (STMT_t FAR 
*) pstmt
->next
) 
1124       if (pstmt
->state 
>= en_stmt_needdata
 
1125           || pstmt
->asyn_on 
!= en_NullProc
) 
1126         /* In this case one need to call  
1127          * SQLCancel() first */ 
1133   if (sqlstat 
== en_00000
) 
1135       hproc 
= _iodbcdm_getproc (hdbc
, en_Disconnect
); 
1137       if (hproc 
== SQL_NULL_HPROC
) 
1143   if (sqlstat 
!= en_00000
) 
1145       PUSHSQLERR (pdbc
->herr
, sqlstat
); 
1150   CALL_DRIVER (hdbc
, retcode
, hproc
, en_Disconnect
, ( 
1153   if (retcode 
== SQL_SUCCESS 
|| retcode 
== SQL_SUCCESS_WITH_INFO
) 
1155       /* diff from MS specs. We disallow 
1156        * driver SQLDisconnect() return 
1157        * SQL_SUCCESS_WITH_INFO and post 
1160       retcode 
= SQL_SUCCESS
; 
1167   /* free all statement handle(s) on this connection */ 
1168   for (; pdbc
->hstmt
;) 
1170       _iodbcdm_dropstmt (pdbc
->hstmt
); 
1173   /* state transition */ 
1174   if (retcode 
== SQL_SUCCESS
) 
1176       pdbc
->state 
= en_dbc_allocated
; 
1186     UCHAR FAR 
* szSqlStrIn
, 
1188     UCHAR FAR 
* szSqlStr
, 
1190     SDWORD FAR 
* pcbSqlStr
) 
1192   DBC_t FAR 
*pdbc 
= (DBC_t FAR 
*) hdbc
; 
1194   int sqlstat 
= en_00000
; 
1197   if (hdbc 
== SQL_NULL_HDBC
) 
1199       return SQL_INVALID_HANDLE
; 
1202   /* check argument */ 
1203   if (szSqlStrIn 
== NULL
) 
1207   else if (cbSqlStrIn 
< 0 && cbSqlStrIn 
!= SQL_NTS
) 
1212   if (sqlstat 
!= en_00000
) 
1214       PUSHSQLERR (pdbc
->herr
, sqlstat
); 
1220   if (pdbc
->state 
<= en_dbc_needdata
) 
1222       PUSHSQLERR (pdbc
->herr
, en_08003
); 
1228   hproc 
= _iodbcdm_getproc (hdbc
, en_NativeSql
); 
1230   if (hproc 
== SQL_NULL_HPROC
) 
1232       PUSHSQLERR (pdbc
->herr
, en_IM001
); 
1237   CALL_DRIVER (hdbc
, retcode
, hproc
, en_NativeSql
, 
1238     (pdbc
->dhdbc
, szSqlStrIn
, cbSqlStrIn
, szSqlStr
, cbSqlStrMax
, pcbSqlStr
))