X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/bd7d06f23d25df834c30d386dcf3b561c4c79a27..b916f809336755620b010293637b12763f01455d:/src/iodbc/connect.c?ds=sidebyside

diff --git a/src/iodbc/connect.c b/src/iodbc/connect.c
index 88e636aca7..2bd934f6a2 100644
--- a/src/iodbc/connect.c
+++ b/src/iodbc/connect.c
@@ -1,33 +1,42 @@
-/** Connect(load) driver
-
-    Copyright (C) 1995 by Ke Jin <kejin@empress.com> 
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program 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 General Public License for more details.
-**/
+/*
+ *  connect.c
+ *
+ *  $Id$
+ *
+ *  Connect (load) driver
+ *
+ *  The iODBC driver manager.
+ *  
+ *  Copyright (C) 1995 by Ke Jin <kejin@empress.com> 
+ *
+ *  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	<../iodbc/iodbc.h>
+#include	"config.h"
 
-#include	<../iodbc/isql.h>
-#include	<../iodbc/isqlext.h>
+#include	"isql.h"
+#include	"isqlext.h"
 
-#include        <../iodbc/dlproc.h>
+#include	"dlproc.h"
 
-#include	<../iodbc/herr.h>
-#include	<../iodbc/henv.h>
-#include	<../iodbc/hdbc.h>
-#include	<../iodbc/hstmt.h>
+#include	"herr.h"
+#include	"henv.h"
+#include	"hdbc.h"
+#include	"hstmt.h"
 
-#include	<../iodbc/itrace.h>
-#include        <strings.h>
-#include        <stdio.h>
+#include	"itrace.h"
 
 extern	char*	_iodbcdm_getkeyvalbydsn();
 extern	char*	_iodbcdm_getkeyvalinstr();
@@ -41,11 +50,8 @@ extern	RETCODE	_iodbcdm_driverunload();
  *   violation.
  */
 static	char sccsid[] 
-	= "@(#)iODBC driver manager " "2.12" ", Copyright(c) 1995 by Ke Jin";
+	= "@(#)iODBC driver manager 2.5, Copyright(c) 1995 by Ke Jin";
 
-static RETCODE	_iodbcdm_driverload( 
-			char FAR* 	path, 	
-			HDBC		hdbc )
 /* - 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)
@@ -53,1210 +59,1183 @@ static RETCODE	_iodbcdm_driverload(
  * - 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 );
+  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;
 
-		return SQL_ERROR;
-	}
+  if (path == NULL || path[0] == '\0')
+    {
+      PUSHSQLERR (pdbc->herr, en_IM002);
 
-	if( hdbc == SQL_NULL_HDBC 
-	 || pdbc->genv == SQL_NULL_HENV )
-	{
-		return SQL_INVALID_HANDLE;
-	}
+      return SQL_ERROR;
+    }
 
-	genv = (GENV_t FAR*)pdbc->genv;
+  if (hdbc == SQL_NULL_HDBC || pdbc->genv == SQL_NULL_HENV)
+    {
+      return SQL_INVALID_HANDLE;
+    }
 
-	hdll = _iodbcdm_dllopen( (char FAR*) path ); 
-				 /* This will either load the
-			    	  * driver dll or increase its
-				  * reference count */
+  genv = (GENV_t FAR *) pdbc->genv;
 
-	if( hdll == SQL_NULL_HDLL )
-	{
-		PUSHSYSERR ( pdbc->herr, _iodbcdm_dllerror() );
-		PUSHSQLERR ( pdbc->herr, en_IM003 );
-		return SQL_ERROR;
-	}
+  /* 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);
+  penv = (ENV_t FAR *) (pdbc->henv);
 
-	if( penv != NULL )
+  if (penv != NULL)
+    {
+      if (penv->hdll != hdll)
 	{
-		if( penv->hdll != hdll )
-		{
-			_iodbcdm_driverunload(hdbc);
-		}
-		else
-		{
-			_iodbcdm_dllclose( hdll );
-			/* this will not unload the driver
-			 * but only decrease its internal
-			 * reference count 
-			 */
-		}
+	  _iodbcdm_driverunload (hdbc);
 	}
-
-	if(penv == NULL )
+      else
 	{
-		/* 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 )
-			{
-				_iodbcdm_dllclose( hdll );
-				/* this will not unload the driver
-				 * but only decrease its internal
-				 * reference count 
-				 */
-				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 */
+	  /* 
+  	   * this will not unload the driver but only decrease its internal
+	   * reference count 
+	   */
+	  _iodbcdm_dllclose (hdll);
 	}
+    }
 
-	/* driver's login timeout option must been set before 
-	 * its SQLConnect() call */
-	if( pdbc->login_timeout != 0UL )
+  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)
 	{
-		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;
-			}
-		}
+	  if (penv->hdll == hdll)
+	    {
+	      /* 
+  	       * this will not unload the driver but only decrease its internal
+	       * reference count 
+	       */
+	      _iodbcdm_dllclose (hdll);
+	      break;
+	    }
 	}
 
-	return SQL_SUCCESS;
-}
-
-RETCODE	_iodbcdm_driverunload( HDBC	hdbc )
-/* - 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
- */
-{
-	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;
-/*	int		sqlstat = en_00000; */
-
-	if( hdbc == SQL_NULL_HDBC )
+      if (penv == NULL)
+	/* no connection attaching with this dll */
 	{
-		return SQL_INVALID_HANDLE;
-	}
+	  int i;
 
-	/* no pointer check will be performed in this function */
-	penv = (ENV_t  FAR*)pdbc->henv;
-	genv = (GENV_t FAR*)pdbc->genv;
+	  /* create a new dll env instance */
+	  penv = (ENV_t FAR *) MEM_ALLOC (sizeof (ENV_t));
 
-	if( penv == NULL 
-	 || penv->hdll == SQL_NULL_HDLL )
-	{
-		return SQL_SUCCESS;
-	}
+	  if (penv == NULL)
+	    {
+	      _iodbcdm_dllclose (hdll);
 
-#if (ODBCVER >= 0x0300)
-	hproc = _iodbcdm_getproc( hdbc, en_FreeHandle );
+	      PUSHSQLERR (pdbc->herr, en_S1001);
 
-	if( hproc )
-	{
-		CALL_DRIVER ( hdbc, retcode, hproc, en_FreeHandle,
-			( SQL_HANDLE_DBC, pdbc->dhdbc ) )
-	}
-	else
-#endif
-	{
-		hproc = _iodbcdm_getproc( hdbc, en_FreeConnect );
+	      return SQL_ERROR;
+	    }
 
-		if( hproc != SQL_NULL_HPROC )
-		{
-			CALL_DRIVER ( hdbc, retcode, hproc, 
-			en_FreeConnect, ( pdbc->dhdbc ) )
+	  for (i = 0; i < SQL_EXT_API_LAST + 1; i++)
+	    {
+	      (penv->dllproc_tab)[i] = SQL_NULL_HPROC;
+	    }
 
-			pdbc->dhdbc = SQL_NULL_HDBC;
-		}
-	}
+	  pdbc->henv = penv;
+	  penv->hdll = hdll;
 
-	penv->refcount --;
+	  /* call driver's SQLAllocHandle() or SQLAllocEnv() */
 
-	if( ! penv->refcount )
-	/* no other connections still attaching with this driver */
-	{
 #if (ODBCVER >= 0x0300)
-		hproc = _iodbcdm_getproc( hdbc, en_FreeHandle );
+	  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 )
+	      if (hproc == SQL_NULL_HPROC)
 		{
-			CALL_DRIVER ( hdbc, retcode, hproc, en_FreeHandle,
-				( SQL_HANDLE_ENV, penv->dhenv ) )
+		  sqlstat = en_IM004;
 		}
-		else
-#endif
+	      else
 		{
-			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;
-			}
+		  CALL_DRIVER (hdbc, retcode, hproc,
+		      en_AllocEnv, (&(penv->dhenv)))
 		}
-
-		_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;
+	    }
+
+	  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
+				 */
 	}
 
-	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 );
+      pdbc->henv = penv;
 
-	if( hproc == SQL_NULL_HPROC )
+      if (pdbc->dhdbc == SQL_NULL_HDBC)
 	{
-		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 (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
 
-	if( pdbc->autocommit != SQL_AUTOCOMMIT_DEFAULT )
-	{
-		CALL_DRIVER ( hdbc, ret, hproc, 
-			en_SetConnectOption, (
-				pdbc->dhdbc,
-				SQL_AUTOCOMMIT,
-				pdbc->autocommit ) )
+	    {
+	      hproc = _iodbcdm_getproc (hdbc, en_AllocConnect);
 
-		retcode |= ret;
-	}
+	      if (hproc == SQL_NULL_HPROC)
+		{
+		  sqlstat = en_IM005;
+		}
+	      else
+		{
+		  CALL_DRIVER (hdbc, retcode, hproc,
+		      en_AllocConnect, (penv->dhenv, &(pdbc->dhdbc)))
+		}
+	    }
 
-	if( pdbc->current_qualifier != NULL )
-	{
-		CALL_DRIVER ( hdbc, ret, hproc, 
-			en_SetConnectOption, (
-				pdbc->dhdbc,
-				SQL_CURRENT_QUALIFIER,
-				pdbc->current_qualifier ) )
+	  if (retcode == SQL_ERROR)
+	    {
+	      sqlstat = en_IM005;
+	    }
 
-		retcode |= ret;
-	}
+	  if (sqlstat != en_00000)
+	    {
+	      _iodbcdm_driverunload (hdbc);
 
-	if( pdbc->packet_size != 0UL )
-	{
-		CALL_DRIVER ( hdbc, ret, hproc,
-			en_SetConnectOption, (
-				pdbc->dhdbc,
-				SQL_PACKET_SIZE,
-				pdbc->packet_size ) )
+	      pdbc->dhdbc = SQL_NULL_HDBC;
+	      PUSHSQLERR (pdbc->herr, en_IM005);
 
-		retcode |= ret;
+	      return SQL_ERROR;
+	    }
 	}
 
-	if( pdbc->quiet_mode != (UDWORD)NULL )
-	{
-		CALL_DRIVER ( hdbc, ret, hproc, 
-			en_SetConnectOption, (
-				pdbc->dhdbc,
-				SQL_QUIET_MODE,
-				pdbc->quiet_mode ) )
+      pdbc->henv = penv;
+      penv->refcount++;		/* bookkeeping reference count on this driver */
+    }
 
-		retcode |= ret;
-	}
+  /* driver's login timeout option must been set before 
+   * its SQLConnect() call */
+  if (pdbc->login_timeout != 0UL)
+    {
+      hproc = _iodbcdm_getproc (hdbc, en_SetConnectOption);
 
-	if( pdbc->txn_isolation != SQL_TXN_READ_UNCOMMITTED )
+      if (hproc == SQL_NULL_HPROC)
 	{
-		CALL_DRIVER ( hdbc, ret, hproc,
-			en_SetConnectOption, (
-				pdbc->dhdbc,
-				SQL_TXN_ISOLATION,
-				pdbc->txn_isolation ) )
+	  sqlstat = en_IM004;
 	}
-
-	/* check error code for driver's SQLSetConnectOption() call */
-	if( retcode != SQL_SUCCESS 
-	 && retcode != SQL_SUCCESS_WITH_INFO )
+      else
 	{
-		PUSHSQLERR ( pdbc->herr, en_IM006 );
+	  CALL_DRIVER (hdbc, retcode, hproc,
+	      en_SetConnectOption, (
+		  pdbc->dhdbc,
+		  SQL_LOGIN_TIMEOUT,
+		  pdbc->login_timeout))
 
-		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 );
+	      if (retcode == SQL_ERROR)
+	    {
+	      PUSHSQLERR (pdbc->herr, en_IM006);
 
-		return retcode;
+	      return SQL_SUCCESS_WITH_INFO;
+	    }
 	}
+    }
 
-	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;
+  return SQL_SUCCESS;
 }
 
-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)
+/* - 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;
-	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 );
+  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;
+    }
 
-		return SQL_ERROR;
-	}
+#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
 
-	if( szDSN == NULL || cbDSN == 0 )
-	{
-		PUSHSQLERR ( pdbc->herr, en_IM002 );
-		
-		return SQL_ERROR;
-	}
+    {
+      hproc = _iodbcdm_getproc (hdbc, en_FreeConnect);
 
-	/* check state */
-	if( pdbc->state != en_dbc_allocated )
+      if (hproc != SQL_NULL_HPROC)
 	{
-		PUSHSQLERR ( pdbc->herr, en_08002 );
+	  CALL_DRIVER (hdbc, retcode, hproc,
+	      en_FreeConnect, (pdbc->dhdbc))
 
-		return SQL_ERROR;
+	      pdbc->dhdbc = SQL_NULL_HDBC;
 	}
+    }
 
-	setopterr |= _iodbcdm_settracing( hdbc, 
-				(char*)szDSN, cbDSN );
-
-	ptr = _iodbcdm_getkeyvalbydsn( szDSN, cbDSN, "Driver", 
-				(char FAR*)driver, sizeof(driver));
+  penv->refcount--;
 
-	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;
-	}
+  if (!penv->refcount)
+    /* no other connections still attaching with this driver */
+    {
 
-	retcode = _iodbcdm_driverload( driver, hdbc );
+#if (ODBCVER >= 0x0300)
+      hproc = _iodbcdm_getproc (hdbc, en_FreeHandle);
 
-	switch( retcode )
+      if (hproc)
 	{
-		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;
+	  CALL_DRIVER (hdbc, retcode, hproc, en_FreeHandle,
+	      (SQL_HANDLE_ENV, penv->dhenv))
 	}
+      else
+#endif
 
-	hproc = _iodbcdm_getproc( hdbc, en_Connect );
-
-	if( hproc == SQL_NULL_HPROC )
 	{
-		_iodbcdm_driverunload( hdbc );
+	  hproc = _iodbcdm_getproc (hdbc, en_FreeEnv);
 
-		PUSHSQLERR ( pdbc->herr, en_IM001 );
+	  if (hproc != SQL_NULL_HPROC)
+	    {
+	      CALL_DRIVER (hdbc, retcode, hproc, en_FreeEnv,
+		  (penv->dhenv))
 
-		return SQL_ERROR;
+		  penv->dhenv = SQL_NULL_HENV;
+	    }
 	}
 
-	CALL_DRIVER ( hdbc, retcode, hproc, en_Connect, (
-			pdbc->dhdbc, 
-			szDSN, 	   cbDSN,
-			szUID,     cbUID,
-			szAuthStr, cbAuthStr ) )
-
-#if 0
-	retcode = hproc(pdbc->dhdbc, 
-			szDSN, 	   cbDSN,
-			szUID,     cbUID,
-			szAuthStr, cbAuthStr );
-#endif
+      _iodbcdm_dllclose (penv->hdll);
+
+      penv->hdll = SQL_NULL_HDLL;
 
-	if( retcode != SQL_SUCCESS 
-	 && retcode != SQL_SUCCESS_WITH_INFO )
+      for (tpenv = (ENV_t FAR *) genv->henv;
+	  tpenv != NULL;
+	  tpenv = (ENV_t FAR *) penv->next)
 	{
-		/* not unload driver for retrive error 
-		 * messge from driver */
-		/*********
-		_iodbcdm_driverunload( hdbc );
-		**********/
+	  if (tpenv == penv)
+	    {
+	      genv->henv = penv->next;
+	      break;
+	    }
 
-		return retcode;
+	  if (tpenv->next == penv)
+	    {
+	      tpenv->next = penv->next;
+	      break;
+	    }
 	}
 
-	/* state transition */
-	pdbc->state = en_dbc_connected;
+      MEM_FREE (penv);
+    }
 
-	/* do delaid option setting */
-	setopterr |= _iodbcdm_dbcdelayset( hdbc );
+  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;
 
-	if( setopterr != SQL_SUCCESS )
-	{
-		return SQL_SUCCESS_WITH_INFO;
-	}
-
-	return retcode;
+  /* 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;
 }
-	
-RETCODE SQL_API	SQLDriverConnect (
-			HDBC		hdbc,
-			HWND		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, dialproc;
 
-	int		sqlstat = en_00000;
-	RETCODE		retcode = SQL_SUCCESS;
-	RETCODE		setopterr = 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;
+}
 
-	if( hdbc == SQL_NULL_HDBC )
-	{
-		return SQL_INVALID_HANDLE;
-	}
 
-	/* check arguments */
-	if( ( cbConnStrIn < 0 && cbConnStrIn != SQL_NTS )
-	 || cbConnStrOutMax < 0 )
-	{
-		PUSHSQLERR (pdbc->herr, en_S1090 );
+static RETCODE 
+_iodbcdm_settracing (HDBC hdbc, char *dsn, int dsnlen)
+{
+  char buf[256];
+  char *ptr;
+  RETCODE setopterr = SQL_SUCCESS;
 
-		return SQL_ERROR;
-	}
+  /* Get Driver's DLL path from specificed or default dsn section */
+  ptr = _iodbcdm_getkeyvalbydsn (dsn, dsnlen, "TraceFile",
+      (char FAR *) buf, sizeof (buf));
 
-	/* check state */
-	if( pdbc->state != en_dbc_allocated )
-	{
-		PUSHSQLERR (pdbc->herr, en_08002 );
+  if (ptr == NULL || ptr[0] == '\0')
+    {
+      ptr = (char FAR *) (SQL_OPT_TRACE_FILE_DEFAULT);
+    }
 
-		return SQL_ERROR;
-	}
+  setopterr |= SQLSetConnectOption (hdbc, SQL_OPT_TRACEFILE, (UDWORD) (ptr));
 
-	drv = _iodbcdm_getkeyvalinstr(szConnStrIn, cbConnStrIn, 
-				"DRIVER", drvbuf, sizeof(drvbuf));
+  ptr = _iodbcdm_getkeyvalbydsn (dsn, dsnlen, "Trace",
+      (char FAR *) buf, sizeof (buf));
 
-	dsn = _iodbcdm_getkeyvalinstr(szConnStrIn, cbConnStrIn,
-				"DSN",	  dsnbuf, sizeof(dsnbuf));
+  if (ptr != NULL)
+    {
+      UDWORD opt = (UDWORD) (-1L);
 
-	switch( fDriverCompletion )
+      if (STREQ (ptr, "ON")
+	  || STREQ (ptr, "On")
+	  || STREQ (ptr, "on")
+	  || STREQ (ptr, "1"))
 	{
-		case SQL_DRIVER_NOPROMPT:
-			break;
-
-		case SQL_DRIVER_COMPLETE:
-		case SQL_DRIVER_COMPLETE_REQUIRED:
-			if( dsn != 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 FAR *)cnstr2drv, "DSN=%s;", dsn);
-			cbConnStrIn += STRLEN(cnstr2drv);
-			STRNCAT( cnstr2drv, szConnStrIn, cbConnStrIn );
-			szConnStrIn = cnstr2drv;
-			break;
-
-		default:
-			sqlstat = en_S1110;
-			break;
+	  opt = SQL_OPT_TRACE_ON;
 	}
 
-	if( sqlstat != en_00000 )
+      if (STREQ (ptr, "OFF")
+	  || STREQ (ptr, "Off")
+	  || STREQ (ptr, "off")
+	  || STREQ (ptr, "0"))
 	{
-		PUSHSQLERR( pdbc->herr, sqlstat );
-		
-		return SQL_ERROR;
+	  opt = SQL_OPT_TRACE_OFF;
 	}
 
-	if( dsn == NULL || dsn[0] == '\0' )
-	{
-		dsn = "default";
-	}
-	else	/* if you want tracing, you must use a DSN */
+      if (opt != (UDWORD) (-1L))
 	{
-		setopterr |= _iodbcdm_settracing( hdbc, 
-					(char*)dsn, SQL_NTS );
+	  setopterr |= SQLSetConnectOption (hdbc,
+	      SQL_OPT_TRACE, opt);
 	}
+    }
 
-	if( drv == NULL || drv[0] == '\0' )
-	{
-		drv = _iodbcdm_getkeyvalbydsn( dsn, SQL_NTS, "Driver", 
-					drvbuf, sizeof(drvbuf));
-	}
+  return setopterr;
+}
 
-	if( drv == NULL )
-	{
-		PUSHSQLERR( pdbc->herr, en_IM002 );
 
-		return SQL_ERROR;
-	}
+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 );
+		**********/
 
-	retcode = _iodbcdm_driverload( drv, hdbc );
+      return retcode;
+    }
 
-	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;
-	}
+  /* state transition */
+  pdbc->state = en_dbc_connected;
 
-	hproc = _iodbcdm_getproc( hdbc, en_DriverConnect );
+  /* do delaid option setting */
+  setopterr |= _iodbcdm_dbcdelayset (hdbc);
 
-	if( hproc == SQL_NULL_HPROC )
-	{
-		_iodbcdm_driverunload( hdbc );
+  if (setopterr != SQL_SUCCESS)
+    {
+      return SQL_SUCCESS_WITH_INFO;
+    }
 
-		PUSHSQLERR ( pdbc->herr, en_IM001 );
+  return retcode;
+}
 
-		return SQL_ERROR;
-	}
-	
-	CALL_DRIVER ( hdbc, retcode, hproc, en_DriverConnect, (
-			pdbc->dhdbc, hwnd,
-			szConnStrIn, cbConnStrIn,
-			szConnStrOut, cbConnStrOutMax,
-			pcbConnStrOut, fDriverCompletion ) )
-
-#if 0
-	retcode = hproc(pdbc->dhdbc, hwnd,
-			szConnStrIn, cbConnStrIn,
-			szConnStrOut, cbConnStrOutMax,
-			pcbConnStrOut, fDriverCompletion );
-#endif
 
-	if( retcode != SQL_SUCCESS 
-	 && retcode != SQL_SUCCESS_WITH_INFO )
-	{
-		/* don't unload driver here for retrive 
-		 * error message from driver */
+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;
-	}
+      return retcode;
+    }
 
-	/* state transition */
-	pdbc->state = en_dbc_connected;
+  /* state transition */
+  pdbc->state = en_dbc_connected;
 
-	/* do delaid option setting */
-	setopterr |= _iodbcdm_dbcdelayset( hdbc );
+  /* do delaid option setting */
+  setopterr |= _iodbcdm_dbcdelayset (hdbc);
 
-	if( setopterr != SQL_SUCCESS )
-	{
-		return SQL_SUCCESS_WITH_INFO;
-	}
+  if (setopterr != SQL_SUCCESS)
+    {
+      return SQL_SUCCESS_WITH_INFO;
+    }
 
-	return retcode;
+  return retcode;
 }
 
-RETCODE SQL_API	SQLBrowseConnect ( 
-			HDBC		hdbc,
-			HWND		hwnd,
-			UCHAR FAR*	szConnStrIn,
-			SWORD 		cbConnStrIn,
-			UCHAR FAR*	szConnStrOut,
-			SWORD		cbConnStrOutMax,
-			SWORD FAR*	pcbConnStrOut )
+
+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;
-/*	HDLL		hdll; */
-	char  FAR*	drv;
-	char		drvbuf[1024];
-	char  FAR*	dsn;
-	char  		dsnbuf[SQL_MAX_DSN_LENGTH + 1];
-/*	UCHAR		cnstr2drv[1024]; */
+  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 /*, dialproc*/ ;
+  HPROC hproc;
 
-/*	int		sqlstat = en_00000; */
-	RETCODE		retcode = SQL_SUCCESS;
-	RETCODE		setopterr = SQL_SUCCESS;
+  RETCODE retcode = SQL_SUCCESS;
+  RETCODE setopterr = SQL_SUCCESS;
 
-	if( hdbc == SQL_NULL_HDBC )
-	{
-		return SQL_INVALID_HANDLE;
-	}
+  if (hdbc == SQL_NULL_HDBC)
+    {
+      return SQL_INVALID_HANDLE;
+    }
 
-	/* check arguments */
-	if( ( cbConnStrIn < 0 && cbConnStrIn != SQL_NTS )
-	 || cbConnStrOutMax < 0 )
-	{
-		PUSHSQLERR (pdbc->herr, en_S1090 );
+  /* check arguments */
+  if ((cbConnStrIn < 0 && cbConnStrIn != SQL_NTS) || cbConnStrOutMax < 0)
+    {
+      PUSHSQLERR (pdbc->herr, en_S1090);
 
-		return SQL_ERROR;
-	}
+      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;
-	}
+  if (pdbc->state == en_dbc_allocated)
+    {
+      drv = _iodbcdm_getkeyvalinstr (szConnStrIn, cbConnStrIn,
+	  "DRIVER", drvbuf, sizeof (drvbuf));
 
-	hproc = _iodbcdm_getproc( hdbc, en_BrowseConnect);
+      dsn = _iodbcdm_getkeyvalinstr (szConnStrIn, cbConnStrIn,
+	  "DSN", dsnbuf, sizeof (dsnbuf));
 
-	if( hproc == SQL_NULL_HPROC )
+      if (dsn == NULL || dsn[0] == '\0')
 	{
-		_iodbcdm_driverunload( hdbc );
-
-		pdbc->state = en_dbc_allocated;
-
-		PUSHSQLERR( pdbc->herr, en_IM001 );
-
-		return SQL_ERROR;
+	  dsn = "default";
 	}
-
-	CALL_DRIVER ( hdbc, retcode, hproc, en_BrowseConnect, (
-			pdbc->dhdbc, hwnd,
-			szConnStrIn, cbConnStrIn,
-			szConnStrOut, cbConnStrOutMax,
-			pcbConnStrOut ) )
-
-#if 0 
-	retcode = hproc(pdbc->dhdbc, hwnd,
-			szConnStrIn, cbConnStrIn,
-			szConnStrOut, cbConnStrOutMax,
-			pcbConnStrOut );
-#endif
-
-	switch( retcode )
+      else
+	/* if you want tracing, you must use a DSN */
 	{
-		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;
+	  setopterr |= _iodbcdm_settracing (hdbc,
+	      (char *) dsn, SQL_NTS);
 	}
 
-	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 )
+      if (drv == NULL || drv[0] == '\0')
 	{
-		return SQL_INVALID_HANDLE;
+	  drv = _iodbcdm_getkeyvalbydsn (dsn, SQL_NTS, "Driver",
+	      drvbuf, sizeof (drvbuf));
 	}
 
-	/* check hdbc state */
-	if ( pdbc->state == en_dbc_allocated )
+      if (drv == NULL)
 	{
-		sqlstat = en_08003;
-	}
+	  PUSHSQLERR (pdbc->herr, en_IM002);
 
-	/* 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;
-		}
+	  return SQL_ERROR;
 	}
 
-	if( sqlstat == en_00000 )
-	{
-		hproc = _iodbcdm_getproc( hdbc, en_Disconnect );
-
-		if( hproc == SQL_NULL_HPROC )
-		{
-			sqlstat = en_IM001;
-		}
-	}
+      retcode = _iodbcdm_driverload (drv, hdbc);
 
-	if( sqlstat != en_00000 )
-	{
-		PUSHSQLERR ( pdbc->herr, sqlstat );
+      switch (retcode)
+	 {
+	 case SQL_SUCCESS:
+	   break;
 
-		return SQL_ERROR;
-	}
-	
-	CALL_DRIVER ( hdbc, retcode, hproc, en_Disconnect, (
-			pdbc->dhdbc ) )
+	 case SQL_SUCCESS_WITH_INFO:
+	   setopterr = SQL_ERROR;
+	   /* unsuccessed in calling driver's 
+	    * SQLSetConnectOption() to set login
+	    * timeout.
+	    */
+	   break;
 
-#if 0
-	retcode = hproc( pdbc->dhdbc );
-#endif
+	 default:
+	   return retcode;
+	 }
+    }
+  else if (pdbc->state != en_dbc_needdata)
+    {
+      PUSHSQLERR (pdbc->herr, en_08002);
 
-	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;
-	}
+      return SQL_ERROR;
+    }
 
-	/* free all statement handle(s) on this connection */
-	for(;pdbc->hstmt;)
-	{
-		_iodbcdm_dropstmt( pdbc->hstmt );
-	}
+  hproc = _iodbcdm_getproc (hdbc, en_BrowseConnect);
 
-#if 0
-	retcode = _iodbcdm_driverunload( hdbc );
-#endif
+  if (hproc == SQL_NULL_HPROC)
+    {
+      _iodbcdm_driverunload (hdbc);
 
-	/* state transition */
-	if( retcode == SQL_SUCCESS )
-	{
-		pdbc->state = en_dbc_allocated;
-	}
+      pdbc->state = en_dbc_allocated;
 
-	return retcode;
-}
+      PUSHSQLERR (pdbc->herr, en_IM001);
 
-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;
-	}
+      return SQL_ERROR;
+    }
 
-	/* check argument */
-	if( szSqlStrIn == NULL )
-	{
-		sqlstat = en_S1009;
-	}
-	else if( cbSqlStrIn < 0
-	      && cbSqlStrIn != SQL_NTS )
-	{
-		sqlstat = en_S1090;
-	}
+  CALL_DRIVER (hdbc, retcode, hproc, en_BrowseConnect, (
+	  pdbc->dhdbc, 
+	  szConnStrIn, cbConnStrIn, 
+	  szConnStrOut, cbConnStrOutMax,
+	  pcbConnStrOut))
 
-	if( sqlstat != en_00000 )
-	{
-		PUSHSQLERR ( pdbc->herr, sqlstat );
+  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;
 
-		return SQL_ERROR;
-	}
+     case SQL_NEED_DATA:
+       pdbc->state = en_dbc_needdata;
+       break;
 
-	/* check state */
-	if( pdbc->state <= en_dbc_needdata )
-	{
-		PUSHSQLERR ( pdbc->herr, en_08003 );
+     case SQL_ERROR:
+       pdbc->state = en_dbc_allocated;
+       /* but the driver will not unloaded 
+        * to allow application retrive err
+        * message from driver 
+        */
+       break;
 
-		return SQL_ERROR;
-	}
+     default:
+       break;
+     }
 
-	/* call driver */
-	hproc = _iodbcdm_getproc( hdbc, en_NativeSql );
+  return retcode;
+}
 
-	if( hproc == SQL_NULL_HPROC )
-	{
-		PUSHSQLERR ( pdbc->herr, en_IM001 );
 
-		return SQL_ERROR;
-	}
+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;
+}
 
-	CALL_DRIVER ( hdbc, retcode, hproc, en_NativeSql, (
-			pdbc->dhdbc,
-			szSqlStrIn,
-			cbSqlStrIn,
-			szSqlStr,
-			cbSqlStrMax,
-			pcbSqlStr ) )
-
-#if 0
-	retcode = hproc(pdbc->dhdbc,
-			szSqlStrIn,
-			cbSqlStrIn,
-			szSqlStr,
-			cbSqlStrMax,
-			pcbSqlStr );
-#endif
 
-	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;
 }