/* * connect.c * * $Id$ * * Connect (load) driver * * The iODBC driver manager. * * Copyright (C) 1995 by Ke Jin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config.h" #include "isql.h" #include "isqlext.h" #include "dlproc.h" #include "herr.h" #include "henv.h" #include "hdbc.h" #include "hstmt.h" #include "itrace.h" extern char* _iodbcdm_getkeyvalbydsn(); extern char* _iodbcdm_getkeyvalinstr(); extern RETCODE _iodbcdm_driverunload(); /* * Following id string is a copyright mark. Removing(i.e. use * souce code of this package without it or make it not appear * in the final object file) or modifing it without permission * from original author(kejin@empress.com) are copyright * violation. */ static char sccsid[] = "@(#)iODBC driver manager 2.5, Copyright(c) 1995 by Ke Jin"; /* - Load driver share library( or increase its reference count * if it has already been loaded by another active connection) * - Call driver's SQLAllocEnv() (for the first reference only) * - Call driver's SQLAllocConnect() * - Call driver's SQLSetConnectOption() (set login time out) * - Increase the bookkeeping reference count */ static RETCODE _iodbcdm_driverload ( char FAR * path, HDBC hdbc) { DBC_t FAR *pdbc = (DBC_t FAR *) hdbc; GENV_t FAR *genv; ENV_t FAR *penv = NULL; HDLL hdll; HPROC hproc; RETCODE retcode = SQL_SUCCESS; int sqlstat = en_00000; if (path == NULL || path[0] == '\0') { PUSHSQLERR (pdbc->herr, en_IM002); return SQL_ERROR; } if (hdbc == SQL_NULL_HDBC || pdbc->genv == SQL_NULL_HENV) { return SQL_INVALID_HANDLE; } genv = (GENV_t FAR *) pdbc->genv; /* This will either load the driver dll or increase its reference count */ hdll = _iodbcdm_dllopen ((char FAR *) path); if (hdll == SQL_NULL_HDLL) { PUSHSYSERR (pdbc->herr, _iodbcdm_dllerror ()); PUSHSQLERR (pdbc->herr, en_IM003); return SQL_ERROR; } penv = (ENV_t FAR *) (pdbc->henv); if (penv != NULL) { if (penv->hdll != hdll) { _iodbcdm_driverunload (hdbc); } else { /* * this will not unload the driver but only decrease its internal * reference count */ _iodbcdm_dllclose (hdll); } } if (penv == NULL) { /* * find out whether this dll has already been loaded on another * connection */ for (penv = (ENV_t FAR *) genv->henv; penv != NULL; penv = (ENV_t FAR *) penv->next) { if (penv->hdll == hdll) { /* * this will not unload the driver but only decrease its internal * reference count */ _iodbcdm_dllclose (hdll); break; } } if (penv == NULL) /* no connection attaching with this dll */ { int i; /* create a new dll env instance */ penv = (ENV_t FAR *) MEM_ALLOC (sizeof (ENV_t)); if (penv == NULL) { _iodbcdm_dllclose (hdll); PUSHSQLERR (pdbc->herr, en_S1001); return SQL_ERROR; } for (i = 0; i < SQL_EXT_API_LAST + 1; i++) { (penv->dllproc_tab)[i] = SQL_NULL_HPROC; } pdbc->henv = penv; penv->hdll = hdll; /* call driver's SQLAllocHandle() or SQLAllocEnv() */ #if (ODBCVER >= 0x0300) hproc = _iodbcdm_getproc (hdbc, en_AllocHandle); if (hproc) { CALL_DRIVER (hdbc, retcode, hproc, en_AllocHandle, (SQL_HANDLE_ENV, SQL_NULL_HANDLE, &(penv->dhenv))) } else /* try driver's SQLAllocEnv() */ #endif { hproc = _iodbcdm_getproc (hdbc, en_AllocEnv); if (hproc == SQL_NULL_HPROC) { sqlstat = en_IM004; } else { CALL_DRIVER (hdbc, retcode, hproc, en_AllocEnv, (&(penv->dhenv))) } } if (retcode == SQL_ERROR) { sqlstat = en_IM004; } if (sqlstat != en_00000) { _iodbcdm_dllclose (hdll); MEM_FREE (penv); PUSHSQLERR (pdbc->herr, en_IM004); return SQL_ERROR; } /* insert into dll env list */ penv->next = (ENV_t FAR *) genv->henv; genv->henv = penv; /* initiate this new env entry */ penv->refcount = 0; /* we will increase it after * driver's SQLAllocConnect() * success */ } pdbc->henv = penv; if (pdbc->dhdbc == SQL_NULL_HDBC) { #if (ODBCVER >= 0x0300) hproc = _iodbcdm_getproc (hdbc, en_AllocHandle); if (hproc) { CALL_DRIVER (hdbc, retcode, hproc, en_AllocHandle, (SQL_HANDLE_DBC, penv->dhenv, &(pdbc->dhdbc))) } else #endif { hproc = _iodbcdm_getproc (hdbc, en_AllocConnect); if (hproc == SQL_NULL_HPROC) { sqlstat = en_IM005; } else { CALL_DRIVER (hdbc, retcode, hproc, en_AllocConnect, (penv->dhenv, &(pdbc->dhdbc))) } } if (retcode == SQL_ERROR) { sqlstat = en_IM005; } if (sqlstat != en_00000) { _iodbcdm_driverunload (hdbc); pdbc->dhdbc = SQL_NULL_HDBC; PUSHSQLERR (pdbc->herr, en_IM005); return SQL_ERROR; } } pdbc->henv = penv; penv->refcount++; /* bookkeeping reference count on this driver */ } /* driver's login timeout option must been set before * its SQLConnect() call */ if (pdbc->login_timeout != 0UL) { hproc = _iodbcdm_getproc (hdbc, en_SetConnectOption); if (hproc == SQL_NULL_HPROC) { sqlstat = en_IM004; } else { CALL_DRIVER (hdbc, retcode, hproc, en_SetConnectOption, ( pdbc->dhdbc, SQL_LOGIN_TIMEOUT, pdbc->login_timeout)) if (retcode == SQL_ERROR) { PUSHSQLERR (pdbc->herr, en_IM006); return SQL_SUCCESS_WITH_INFO; } } } return SQL_SUCCESS; } /* - Call driver's SQLFreeConnect() * - Call driver's SQLFreeEnv() ( for the last reference only) * - Unload the share library( or decrease its reference * count if it is not the last referenct ) * - decrease bookkeeping reference count * - state transition to allocated */ RETCODE _iodbcdm_driverunload (HDBC hdbc) { DBC_t FAR *pdbc = (DBC_t FAR *) hdbc; ENV_t FAR *penv; ENV_t FAR *tpenv; GENV_t FAR *genv; HPROC hproc; RETCODE retcode = SQL_SUCCESS; if (hdbc == SQL_NULL_HDBC) { return SQL_INVALID_HANDLE; } /* no pointer check will be performed in this function */ penv = (ENV_t FAR *) pdbc->henv; genv = (GENV_t FAR *) pdbc->genv; if (penv == NULL || penv->hdll == SQL_NULL_HDLL) { return SQL_SUCCESS; } #if (ODBCVER >= 0x0300) hproc = _iodbcdm_getproc (hdbc, en_FreeHandle); if (hproc) { CALL_DRIVER (hdbc, retcode, hproc, en_FreeHandle, (SQL_HANDLE_DBC, pdbc->dhdbc)) } else #endif { hproc = _iodbcdm_getproc (hdbc, en_FreeConnect); if (hproc != SQL_NULL_HPROC) { CALL_DRIVER (hdbc, retcode, hproc, en_FreeConnect, (pdbc->dhdbc)) pdbc->dhdbc = SQL_NULL_HDBC; } } penv->refcount--; if (!penv->refcount) /* no other connections still attaching with this driver */ { #if (ODBCVER >= 0x0300) hproc = _iodbcdm_getproc (hdbc, en_FreeHandle); if (hproc) { CALL_DRIVER (hdbc, retcode, hproc, en_FreeHandle, (SQL_HANDLE_ENV, penv->dhenv)) } else #endif { hproc = _iodbcdm_getproc (hdbc, en_FreeEnv); if (hproc != SQL_NULL_HPROC) { CALL_DRIVER (hdbc, retcode, hproc, en_FreeEnv, (penv->dhenv)) penv->dhenv = SQL_NULL_HENV; } } _iodbcdm_dllclose (penv->hdll); penv->hdll = SQL_NULL_HDLL; for (tpenv = (ENV_t FAR *) genv->henv; tpenv != NULL; tpenv = (ENV_t FAR *) penv->next) { if (tpenv == penv) { genv->henv = penv->next; break; } if (tpenv->next == penv) { tpenv->next = penv->next; break; } } MEM_FREE (penv); } pdbc->henv = SQL_NULL_HENV; pdbc->hstmt = SQL_NULL_HSTMT; /* pdbc->herr = SQL_NULL_HERR; -- delay to DM's SQLFreeConnect() */ pdbc->dhdbc = SQL_NULL_HDBC; pdbc->state = en_dbc_allocated; /* set connect options to default values */ /********** pdbc->access_mode = SQL_MODE_DEFAULT; pdbc->autocommit = SQL_AUTOCOMMIT_DEFAULT; pdbc->login_timeout = 0UL; **********/ pdbc->odbc_cursors = SQL_CUR_DEFAULT; pdbc->packet_size = 0UL; pdbc->quiet_mode = (UDWORD) NULL; pdbc->txn_isolation = SQL_TXN_READ_UNCOMMITTED; if (pdbc->current_qualifier != NULL) { MEM_FREE (pdbc->current_qualifier); pdbc->current_qualifier = NULL; } return SQL_SUCCESS; } static RETCODE _iodbcdm_dbcdelayset (HDBC hdbc) { DBC_t FAR *pdbc = (DBC_t FAR *) hdbc; ENV_t FAR *penv; HPROC hproc; RETCODE retcode = SQL_SUCCESS; RETCODE ret; penv = pdbc->henv; hproc = _iodbcdm_getproc (hdbc, en_SetConnectOption); if (hproc == SQL_NULL_HPROC) { PUSHSQLERR (pdbc->herr, en_IM006); return SQL_SUCCESS_WITH_INFO; } if (pdbc->access_mode != SQL_MODE_DEFAULT) { CALL_DRIVER (hdbc, ret, hproc, en_SetConnectOption, ( SQL_ACCESS_MODE, pdbc->access_mode)) retcode |= ret; } if (pdbc->autocommit != SQL_AUTOCOMMIT_DEFAULT) { CALL_DRIVER (hdbc, ret, hproc, en_SetConnectOption, ( pdbc->dhdbc, SQL_AUTOCOMMIT, pdbc->autocommit)) retcode |= ret; } if (pdbc->current_qualifier != NULL) { CALL_DRIVER (hdbc, ret, hproc, en_SetConnectOption, ( pdbc->dhdbc, SQL_CURRENT_QUALIFIER, pdbc->current_qualifier)) retcode |= ret; } if (pdbc->packet_size != 0UL) { CALL_DRIVER (hdbc, ret, hproc, en_SetConnectOption, ( pdbc->dhdbc, SQL_PACKET_SIZE, pdbc->packet_size)) retcode |= ret; } if (pdbc->quiet_mode != (UDWORD) NULL) { CALL_DRIVER (hdbc, ret, hproc, en_SetConnectOption, ( pdbc->dhdbc, SQL_QUIET_MODE, pdbc->quiet_mode)) retcode |= ret; } if (pdbc->txn_isolation != SQL_TXN_READ_UNCOMMITTED) { CALL_DRIVER (hdbc, ret, hproc, en_SetConnectOption, ( pdbc->dhdbc, SQL_TXN_ISOLATION, pdbc->txn_isolation)) } /* check error code for driver's SQLSetConnectOption() call */ if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) { PUSHSQLERR (pdbc->herr, en_IM006); retcode = SQL_ERROR; } /* get cursor behavior on transaction commit or rollback */ hproc = _iodbcdm_getproc (hdbc, en_GetInfo); if (hproc == SQL_NULL_HPROC) { PUSHSQLERR (pdbc->herr, en_01000); return retcode; } CALL_DRIVER (hdbc, ret, hproc, en_GetInfo, ( pdbc->dhdbc, SQL_CURSOR_COMMIT_BEHAVIOR, (PTR) & (pdbc->cb_commit), sizeof (pdbc->cb_commit), NULL)) retcode |= ret; CALL_DRIVER (hdbc, ret, hproc, en_GetInfo, ( pdbc->dhdbc, SQL_CURSOR_ROLLBACK_BEHAVIOR, (PTR) & (pdbc->cb_rollback), sizeof (pdbc->cb_rollback), NULL)) retcode |= ret; if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) { return SQL_ERROR; } return retcode; } static RETCODE _iodbcdm_settracing (HDBC hdbc, char *dsn, int dsnlen) { char buf[256]; char *ptr; RETCODE setopterr = SQL_SUCCESS; /* Get Driver's DLL path from specificed or default dsn section */ ptr = _iodbcdm_getkeyvalbydsn (dsn, dsnlen, "TraceFile", (char FAR *) buf, sizeof (buf)); if (ptr == NULL || ptr[0] == '\0') { ptr = (char FAR *) (SQL_OPT_TRACE_FILE_DEFAULT); } setopterr |= SQLSetConnectOption (hdbc, SQL_OPT_TRACEFILE, (UDWORD) (ptr)); ptr = _iodbcdm_getkeyvalbydsn (dsn, dsnlen, "Trace", (char FAR *) buf, sizeof (buf)); if (ptr != NULL) { UDWORD opt = (UDWORD) (-1L); if (STREQ (ptr, "ON") || STREQ (ptr, "On") || STREQ (ptr, "on") || STREQ (ptr, "1")) { opt = SQL_OPT_TRACE_ON; } if (STREQ (ptr, "OFF") || STREQ (ptr, "Off") || STREQ (ptr, "off") || STREQ (ptr, "0")) { opt = SQL_OPT_TRACE_OFF; } if (opt != (UDWORD) (-1L)) { setopterr |= SQLSetConnectOption (hdbc, SQL_OPT_TRACE, opt); } } return setopterr; } RETCODE SQL_API SQLConnect ( HDBC hdbc, UCHAR FAR * szDSN, SWORD cbDSN, UCHAR FAR * szUID, SWORD cbUID, UCHAR FAR * szAuthStr, SWORD cbAuthStr) { DBC_t FAR *pdbc = (DBC_t FAR *) hdbc; RETCODE retcode = SQL_SUCCESS; RETCODE setopterr = SQL_SUCCESS; char driver[1024] = {'\0'}; /* MS SDK Guide * specifies driver * path can't longer * than 255. */ char *ptr; HPROC hproc; if (hdbc == SQL_NULL_HDBC) { return SQL_INVALID_HANDLE; } /* check arguments */ if ((cbDSN < 0 && cbDSN != SQL_NTS) || (cbUID < 0 && cbUID != SQL_NTS) || (cbAuthStr < 0 && cbAuthStr != SQL_NTS) || (cbDSN > SQL_MAX_DSN_LENGTH)) { PUSHSQLERR (pdbc->herr, en_S1090); return SQL_ERROR; } if (szDSN == NULL || cbDSN == 0) { PUSHSQLERR (pdbc->herr, en_IM002); return SQL_ERROR; } /* check state */ if (pdbc->state != en_dbc_allocated) { PUSHSQLERR (pdbc->herr, en_08002); return SQL_ERROR; } setopterr |= _iodbcdm_settracing (hdbc, (char *) szDSN, cbDSN); ptr = _iodbcdm_getkeyvalbydsn (szDSN, cbDSN, "Driver", (char FAR *) driver, sizeof (driver)); if (ptr == NULL) /* No specified or default dsn section or * no driver specification in this dsn section */ { PUSHSQLERR (pdbc->herr, en_IM002); return SQL_ERROR; } retcode = _iodbcdm_driverload (driver, hdbc); switch (retcode) { case SQL_SUCCESS: break; case SQL_SUCCESS_WITH_INFO: setopterr = SQL_ERROR; /* unsuccessed in calling driver's * SQLSetConnectOption() to set login * timeout. */ break; default: return retcode; } hproc = _iodbcdm_getproc (hdbc, en_Connect); if (hproc == SQL_NULL_HPROC) { _iodbcdm_driverunload (hdbc); PUSHSQLERR (pdbc->herr, en_IM001); return SQL_ERROR; } CALL_DRIVER (hdbc, retcode, hproc, en_Connect, ( pdbc->dhdbc, szDSN, cbDSN, szUID, cbUID, szAuthStr, cbAuthStr)) if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) { /* not unload driver for retrive error * messge from driver */ /********* _iodbcdm_driverunload( hdbc ); **********/ return retcode; } /* state transition */ pdbc->state = en_dbc_connected; /* do delaid option setting */ setopterr |= _iodbcdm_dbcdelayset (hdbc); if (setopterr != SQL_SUCCESS) { return SQL_SUCCESS_WITH_INFO; } return retcode; } RETCODE SQL_API SQLDriverConnect ( HDBC hdbc, SQLHWND hwnd, UCHAR FAR * szConnStrIn, SWORD cbConnStrIn, UCHAR FAR * szConnStrOut, SWORD cbConnStrOutMax, SWORD FAR * pcbConnStrOut, UWORD fDriverCompletion) { DBC_t FAR *pdbc = (DBC_t FAR *) hdbc; HDLL hdll; char FAR *drv; char drvbuf[1024]; char FAR *dsn; char dsnbuf[SQL_MAX_DSN_LENGTH + 1]; UCHAR cnstr2drv[1024]; HPROC hproc; HPROC dialproc; int sqlstat = en_00000; RETCODE retcode = SQL_SUCCESS; RETCODE setopterr = SQL_SUCCESS; if (hdbc == SQL_NULL_HDBC) { return SQL_INVALID_HANDLE; } /* check arguments */ if ((cbConnStrIn < 0 && cbConnStrIn != SQL_NTS) || cbConnStrOutMax < 0) { PUSHSQLERR (pdbc->herr, en_S1090); return SQL_ERROR; } /* check state */ if (pdbc->state != en_dbc_allocated) { PUSHSQLERR (pdbc->herr, en_08002); return SQL_ERROR; } drv = _iodbcdm_getkeyvalinstr (szConnStrIn, cbConnStrIn, "DRIVER", drvbuf, sizeof (drvbuf)); dsn = _iodbcdm_getkeyvalinstr (szConnStrIn, cbConnStrIn, "DSN", dsnbuf, sizeof (dsnbuf)); switch (fDriverCompletion) { case SQL_DRIVER_NOPROMPT: break; case SQL_DRIVER_COMPLETE: case SQL_DRIVER_COMPLETE_REQUIRED: if (dsn != NULL || drv != NULL) { break; } /* fall to next case */ case SQL_DRIVER_PROMPT: /* Get data source dialog box function from * current executable */ hdll = _iodbcdm_dllopen ((char FAR *) NULL); dialproc = _iodbcdm_dllproc (hdll, "_iodbcdm_drvconn_dialbox"); if (dialproc == SQL_NULL_HPROC) { sqlstat = en_IM008; break; } retcode = dialproc ( hwnd, /* window or display handle */ dsnbuf, /* input/output dsn buf */ sizeof (dsnbuf), /* buf size */ &sqlstat); /* error code */ if (retcode != SQL_SUCCESS) { break; } if (cbConnStrIn == SQL_NTS) { cbConnStrIn = STRLEN (szConnStrIn); } dsn = dsnbuf; if (dsn[0] == '\0') { dsn = "default"; } if (cbConnStrIn > sizeof (cnstr2drv) - STRLEN (dsn) - STRLEN ("DSN=;") - 1) { sqlstat = en_S1001; /* a lazy way to avoid * using heap memory */ break; } sprintf ((char*)cnstr2drv, "DSN=%s;", dsn); cbConnStrIn += STRLEN (cnstr2drv); STRNCAT (cnstr2drv, szConnStrIn, cbConnStrIn); szConnStrIn = cnstr2drv; break; default: sqlstat = en_S1110; break; } if (sqlstat != en_00000) { PUSHSQLERR (pdbc->herr, sqlstat); return SQL_ERROR; } if (dsn == NULL || dsn[0] == '\0') { dsn = "default"; } else /* if you want tracing, you must use a DSN */ { setopterr |= _iodbcdm_settracing (hdbc, (char *) dsn, SQL_NTS); } if (drv == NULL || drv[0] == '\0') { drv = _iodbcdm_getkeyvalbydsn (dsn, SQL_NTS, "Driver", drvbuf, sizeof (drvbuf)); } if (drv == NULL) { PUSHSQLERR (pdbc->herr, en_IM002); return SQL_ERROR; } retcode = _iodbcdm_driverload (drv, hdbc); switch (retcode) { case SQL_SUCCESS: break; case SQL_SUCCESS_WITH_INFO: setopterr = SQL_ERROR; /* unsuccessed in calling driver's * SQLSetConnectOption() to set login * timeout. */ break; default: return retcode; } hproc = _iodbcdm_getproc (hdbc, en_DriverConnect); if (hproc == SQL_NULL_HPROC) { _iodbcdm_driverunload (hdbc); PUSHSQLERR (pdbc->herr, en_IM001); return SQL_ERROR; } CALL_DRIVER (hdbc, retcode, hproc, en_DriverConnect, ( pdbc->dhdbc, hwnd, szConnStrIn, cbConnStrIn, szConnStrOut, cbConnStrOutMax, pcbConnStrOut, fDriverCompletion)) if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) { /* don't unload driver here for retrive * error message from driver */ /******** _iodbcdm_driverunload( hdbc ); *********/ return retcode; } /* state transition */ pdbc->state = en_dbc_connected; /* do delaid option setting */ setopterr |= _iodbcdm_dbcdelayset (hdbc); if (setopterr != SQL_SUCCESS) { return SQL_SUCCESS_WITH_INFO; } return retcode; } RETCODE SQL_API SQLBrowseConnect ( HDBC hdbc, UCHAR FAR * szConnStrIn, SWORD cbConnStrIn, UCHAR FAR * szConnStrOut, SWORD cbConnStrOutMax, SWORD FAR * pcbConnStrOut) { DBC_t FAR *pdbc = (DBC_t FAR *) hdbc; char FAR *drv; char drvbuf[1024]; char FAR *dsn; char dsnbuf[SQL_MAX_DSN_LENGTH + 1]; HPROC hproc; RETCODE retcode = SQL_SUCCESS; RETCODE setopterr = SQL_SUCCESS; if (hdbc == SQL_NULL_HDBC) { return SQL_INVALID_HANDLE; } /* check arguments */ if ((cbConnStrIn < 0 && cbConnStrIn != SQL_NTS) || cbConnStrOutMax < 0) { PUSHSQLERR (pdbc->herr, en_S1090); return SQL_ERROR; } if (pdbc->state == en_dbc_allocated) { drv = _iodbcdm_getkeyvalinstr (szConnStrIn, cbConnStrIn, "DRIVER", drvbuf, sizeof (drvbuf)); dsn = _iodbcdm_getkeyvalinstr (szConnStrIn, cbConnStrIn, "DSN", dsnbuf, sizeof (dsnbuf)); if (dsn == NULL || dsn[0] == '\0') { dsn = "default"; } else /* if you want tracing, you must use a DSN */ { setopterr |= _iodbcdm_settracing (hdbc, (char *) dsn, SQL_NTS); } if (drv == NULL || drv[0] == '\0') { drv = _iodbcdm_getkeyvalbydsn (dsn, SQL_NTS, "Driver", drvbuf, sizeof (drvbuf)); } if (drv == NULL) { PUSHSQLERR (pdbc->herr, en_IM002); return SQL_ERROR; } retcode = _iodbcdm_driverload (drv, hdbc); switch (retcode) { case SQL_SUCCESS: break; case SQL_SUCCESS_WITH_INFO: setopterr = SQL_ERROR; /* unsuccessed in calling driver's * SQLSetConnectOption() to set login * timeout. */ break; default: return retcode; } } else if (pdbc->state != en_dbc_needdata) { PUSHSQLERR (pdbc->herr, en_08002); return SQL_ERROR; } hproc = _iodbcdm_getproc (hdbc, en_BrowseConnect); if (hproc == SQL_NULL_HPROC) { _iodbcdm_driverunload (hdbc); pdbc->state = en_dbc_allocated; PUSHSQLERR (pdbc->herr, en_IM001); return SQL_ERROR; } CALL_DRIVER (hdbc, retcode, hproc, en_BrowseConnect, ( pdbc->dhdbc, szConnStrIn, cbConnStrIn, szConnStrOut, cbConnStrOutMax, pcbConnStrOut)) switch (retcode) { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: pdbc->state = en_dbc_connected; setopterr |= _iodbcdm_dbcdelayset (hdbc); if (setopterr != SQL_SUCCESS) { retcode = SQL_SUCCESS_WITH_INFO; } break; case SQL_NEED_DATA: pdbc->state = en_dbc_needdata; break; case SQL_ERROR: pdbc->state = en_dbc_allocated; /* but the driver will not unloaded * to allow application retrive err * message from driver */ break; default: break; } return retcode; } RETCODE SQL_API SQLDisconnect (HDBC hdbc) { DBC_t FAR *pdbc = (DBC_t *) hdbc; STMT_t FAR *pstmt; RETCODE retcode; HPROC hproc; int sqlstat = en_00000; if (hdbc == SQL_NULL_HDBC) { return SQL_INVALID_HANDLE; } /* check hdbc state */ if (pdbc->state == en_dbc_allocated) { sqlstat = en_08003; } /* check stmt(s) state */ for (pstmt = (STMT_t FAR *) pdbc->hstmt; pstmt != NULL && sqlstat == en_00000; pstmt = (STMT_t FAR *) pstmt->next) { if (pstmt->state >= en_stmt_needdata || pstmt->asyn_on != en_NullProc) /* In this case one need to call * SQLCancel() first */ { sqlstat = en_S1010; } } if (sqlstat == en_00000) { hproc = _iodbcdm_getproc (hdbc, en_Disconnect); if (hproc == SQL_NULL_HPROC) { sqlstat = en_IM001; } } if (sqlstat != en_00000) { PUSHSQLERR (pdbc->herr, sqlstat); return SQL_ERROR; } CALL_DRIVER (hdbc, retcode, hproc, en_Disconnect, ( pdbc->dhdbc)) if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) { /* diff from MS specs. We disallow * driver SQLDisconnect() return * SQL_SUCCESS_WITH_INFO and post * error message. */ retcode = SQL_SUCCESS; } else { return retcode; } /* free all statement handle(s) on this connection */ for (; pdbc->hstmt;) { _iodbcdm_dropstmt (pdbc->hstmt); } /* state transition */ if (retcode == SQL_SUCCESS) { pdbc->state = en_dbc_allocated; } return retcode; } RETCODE SQL_API SQLNativeSql ( HDBC hdbc, UCHAR FAR * szSqlStrIn, SDWORD cbSqlStrIn, UCHAR FAR * szSqlStr, SDWORD cbSqlStrMax, SDWORD FAR * pcbSqlStr) { DBC_t FAR *pdbc = (DBC_t FAR *) hdbc; HPROC hproc; int sqlstat = en_00000; RETCODE retcode; if (hdbc == SQL_NULL_HDBC) { return SQL_INVALID_HANDLE; } /* check argument */ if (szSqlStrIn == NULL) { sqlstat = en_S1009; } else if (cbSqlStrIn < 0 && cbSqlStrIn != SQL_NTS) { sqlstat = en_S1090; } if (sqlstat != en_00000) { PUSHSQLERR (pdbc->herr, sqlstat); return SQL_ERROR; } /* check state */ if (pdbc->state <= en_dbc_needdata) { PUSHSQLERR (pdbc->herr, en_08003); return SQL_ERROR; } /* call driver */ hproc = _iodbcdm_getproc (hdbc, en_NativeSql); if (hproc == SQL_NULL_HPROC) { PUSHSQLERR (pdbc->herr, en_IM001); return SQL_ERROR; } CALL_DRIVER (hdbc, retcode, hproc, en_NativeSql, (pdbc->dhdbc, szSqlStrIn, cbSqlStrIn, szSqlStr, cbSqlStrMax, pcbSqlStr)) return retcode; }