1 /*
2  *  connect.c
3  *
4  *  $Id: connect.c 5545 2000-01-20 13:19:20Z GT $
5  *
6  *  Connect (load) driver
7  *
8  *  The iODBC driver manager.
9  *
10  *  Copyright (C) 1995 by Ke Jin <kejin@empress.com>
11  *
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.
16  *
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.
21  *
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.
25  */
26 
27 #include	"config.h"
28 
29 #include	"isql.h"
30 #include	"isqlext.h"
31 
32 #include	"dlproc.h"
33 
34 #include	"herr.h"
35 #include	"henv.h"
36 #include	"hdbc.h"
37 #include	"hstmt.h"
38 
39 #include	"itrace.h"
40 
41 extern	char*	_iodbcdm_getkeyvalbydsn();
42 extern	char*	_iodbcdm_getkeyvalinstr();
43 extern	RETCODE	_iodbcdm_driverunload();
44 
45 /*
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
50  *   violation.
51  */
52 static	char sccsid[]
53 	= "@(#)iODBC driver manager 2.5, Copyright(c) 1995 by Ke Jin";
54 
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
61  */
62 static RETCODE
_iodbcdm_driverload(char FAR * path,HDBC hdbc)63 _iodbcdm_driverload (
64     char FAR * path,
65     HDBC hdbc)
66 {
67   DBC_t FAR *pdbc = (DBC_t FAR *) hdbc;
68   GENV_t FAR *genv;
69   ENV_t FAR *penv = NULL;
70   HDLL hdll;
71   HPROC hproc;
72   RETCODE retcode = SQL_SUCCESS;
73   int sqlstat = en_00000;
74 
75   if (path == NULL || path[0] == '\0')
76     {
77       PUSHSQLERR (pdbc->herr, en_IM002);
78 
79       return SQL_ERROR;
80     }
81 
82   if (hdbc == SQL_NULL_HDBC || pdbc->genv == SQL_NULL_HENV)
83     {
84       return SQL_INVALID_HANDLE;
85     }
86 
87   genv = (GENV_t FAR *) pdbc->genv;
88 
89   /* This will either load the driver dll or increase its reference count */
90   hdll = _iodbcdm_dllopen ((char FAR *) path);
91 
92   if (hdll == SQL_NULL_HDLL)
93     {
94       PUSHSYSERR (pdbc->herr, _iodbcdm_dllerror ());
95       PUSHSQLERR (pdbc->herr, en_IM003);
96       return SQL_ERROR;
97     }
98 
99   penv = (ENV_t FAR *) (pdbc->henv);
100 
101   if (penv != NULL)
102     {
103       if (penv->hdll != hdll)
104 	{
105 	  _iodbcdm_driverunload (hdbc);
106 	}
107       else
108 	{
109 	  /*
110   	   * this will not unload the driver but only decrease its internal
111 	   * reference count
112 	   */
113 	  _iodbcdm_dllclose (hdll);
114 	}
115     }
116 
117   if (penv == NULL)
118     {
119       /*
120        * find out whether this dll has already been loaded on another
121        * connection
122        */
123       for (penv = (ENV_t FAR *) genv->henv;
124 	  penv != NULL;
125 	  penv = (ENV_t FAR *) penv->next)
126 	{
127 	  if (penv->hdll == hdll)
128 	    {
129 	      /*
130   	       * this will not unload the driver but only decrease its internal
131 	       * reference count
132 	       */
133 	      _iodbcdm_dllclose (hdll);
134 	      break;
135 	    }
136 	}
137 
138       if (penv == NULL)
139 	/* no connection attaching with this dll */
140 	{
141 	  int i;
142 
143 	  /* create a new dll env instance */
144 	  penv = (ENV_t FAR *) MEM_ALLOC (sizeof (ENV_t));
145 
146 	  if (penv == NULL)
147 	    {
148 	      _iodbcdm_dllclose (hdll);
149 
150 	      PUSHSQLERR (pdbc->herr, en_S1001);
151 
152 	      return SQL_ERROR;
153 	    }
154 
155 	  for (i = 0; i < SQL_EXT_API_LAST + 1; i++)
156 	    {
157 	      (penv->dllproc_tab)[i] = SQL_NULL_HPROC;
158 	    }
159 
160 	  pdbc->henv = penv;
161 	  penv->hdll = hdll;
162 
163 	  /* call driver's SQLAllocHandle() or SQLAllocEnv() */
164 
165 #if (ODBCVER >= 0x0300)
166 	  hproc = _iodbcdm_getproc (hdbc, en_AllocHandle);
167 
168 	  if (hproc)
169 	    {
170 	      CALL_DRIVER (hdbc, retcode, hproc, en_AllocHandle,
171 		  (SQL_HANDLE_ENV, SQL_NULL_HANDLE, &(penv->dhenv)))
172 	    }
173 	  else			/* try driver's SQLAllocEnv() */
174 #endif
175 	    {
176 	      hproc = _iodbcdm_getproc (hdbc, en_AllocEnv);
177 
178 	      if (hproc == SQL_NULL_HPROC)
179 		{
180 		  sqlstat = en_IM004;
181 		}
182 	      else
183 		{
184 		  CALL_DRIVER (hdbc, retcode, hproc,
185 		      en_AllocEnv, (&(penv->dhenv)))
186 		}
187 	    }
188 
189 	  if (retcode == SQL_ERROR)
190 	    {
191 	      sqlstat = en_IM004;
192 	    }
193 
194 	  if (sqlstat != en_00000)
195 	    {
196 	      _iodbcdm_dllclose (hdll);
197 	      MEM_FREE (penv);
198 	      PUSHSQLERR (pdbc->herr, en_IM004);
199 
200 	      return SQL_ERROR;
201 	    }
202 
203 	  /* insert into dll env list */
204 	  penv->next = (ENV_t FAR *) genv->henv;
205 	  genv->henv = penv;
206 
207 	  /* initiate this new env entry */
208 	  penv->refcount = 0;	/* we will increase it after
209 				 * driver's SQLAllocConnect()
210 				 * success
211 				 */
212 	}
213 
214       pdbc->henv = penv;
215 
216       if (pdbc->dhdbc == SQL_NULL_HDBC)
217 	{
218 
219 #if (ODBCVER >= 0x0300)
220 	  hproc = _iodbcdm_getproc (hdbc, en_AllocHandle);
221 
222 	  if (hproc)
223 	    {
224 	      CALL_DRIVER (hdbc, retcode, hproc, en_AllocHandle,
225 		  (SQL_HANDLE_DBC, penv->dhenv, &(pdbc->dhdbc)))
226 	    }
227 	  else
228 #endif
229 
230 	    {
231 	      hproc = _iodbcdm_getproc (hdbc, en_AllocConnect);
232 
233 	      if (hproc == SQL_NULL_HPROC)
234 		{
235 		  sqlstat = en_IM005;
236 		}
237 	      else
238 		{
239 		  CALL_DRIVER (hdbc, retcode, hproc,
240 		      en_AllocConnect, (penv->dhenv, &(pdbc->dhdbc)))
241 		}
242 	    }
243 
244 	  if (retcode == SQL_ERROR)
245 	    {
246 	      sqlstat = en_IM005;
247 	    }
248 
249 	  if (sqlstat != en_00000)
250 	    {
251 	      _iodbcdm_driverunload (hdbc);
252 
253 	      pdbc->dhdbc = SQL_NULL_HDBC;
254 	      PUSHSQLERR (pdbc->herr, en_IM005);
255 
256 	      return SQL_ERROR;
257 	    }
258 	}
259 
260       pdbc->henv = penv;
261       penv->refcount++;		/* bookkeeping reference count on this driver */
262     }
263 
264   /* driver's login timeout option must been set before
265    * its SQLConnect() call */
266   if (pdbc->login_timeout != 0UL)
267     {
268       hproc = _iodbcdm_getproc (hdbc, en_SetConnectOption);
269 
270       if (hproc == SQL_NULL_HPROC)
271 	{
272 	  sqlstat = en_IM004;
273 	}
274       else
275 	{
276 	  CALL_DRIVER (hdbc, retcode, hproc,
277 	      en_SetConnectOption, (
278 		  pdbc->dhdbc,
279 		  SQL_LOGIN_TIMEOUT,
280 		  pdbc->login_timeout))
281 
282 	      if (retcode == SQL_ERROR)
283 	    {
284 	      PUSHSQLERR (pdbc->herr, en_IM006);
285 
286 	      return SQL_SUCCESS_WITH_INFO;
287 	    }
288 	}
289     }
290 
291   return SQL_SUCCESS;
292 }
293 
294 
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
301  */
302 RETCODE
_iodbcdm_driverunload(HDBC hdbc)303 _iodbcdm_driverunload (HDBC hdbc)
304 {
305   DBC_t FAR *pdbc = (DBC_t FAR *) hdbc;
306   ENV_t FAR *penv;
307   ENV_t FAR *tpenv;
308   GENV_t FAR *genv;
309   HPROC hproc;
310   RETCODE retcode = SQL_SUCCESS;
311 
312   if (hdbc == SQL_NULL_HDBC)
313     {
314       return SQL_INVALID_HANDLE;
315     }
316 
317   /* no pointer check will be performed in this function */
318   penv = (ENV_t FAR *) pdbc->henv;
319   genv = (GENV_t FAR *) pdbc->genv;
320 
321   if (penv == NULL || penv->hdll == SQL_NULL_HDLL)
322     {
323       return SQL_SUCCESS;
324     }
325 
326 #if (ODBCVER >= 0x0300)
327   hproc = _iodbcdm_getproc (hdbc, en_FreeHandle);
328 
329   if (hproc)
330     {
331       CALL_DRIVER (hdbc, retcode, hproc, en_FreeHandle,
332 	  (SQL_HANDLE_DBC, pdbc->dhdbc))
333     }
334   else
335 #endif
336 
337     {
338       hproc = _iodbcdm_getproc (hdbc, en_FreeConnect);
339 
340       if (hproc != SQL_NULL_HPROC)
341 	{
342 	  CALL_DRIVER (hdbc, retcode, hproc,
343 	      en_FreeConnect, (pdbc->dhdbc))
344 
345 	      pdbc->dhdbc = SQL_NULL_HDBC;
346 	}
347     }
348 
349   penv->refcount--;
350 
351   if (!penv->refcount)
352     /* no other connections still attaching with this driver */
353     {
354 
355 #if (ODBCVER >= 0x0300)
356       hproc = _iodbcdm_getproc (hdbc, en_FreeHandle);
357 
358       if (hproc)
359 	{
360 	  CALL_DRIVER (hdbc, retcode, hproc, en_FreeHandle,
361 	      (SQL_HANDLE_ENV, penv->dhenv))
362 	}
363       else
364 #endif
365 
366 	{
367 	  hproc = _iodbcdm_getproc (hdbc, en_FreeEnv);
368 
369 	  if (hproc != SQL_NULL_HPROC)
370 	    {
371 	      CALL_DRIVER (hdbc, retcode, hproc, en_FreeEnv,
372 		  (penv->dhenv))
373 
374 		  penv->dhenv = SQL_NULL_HENV;
375 	    }
376 	}
377 
378       _iodbcdm_dllclose (penv->hdll);
379 
380       penv->hdll = SQL_NULL_HDLL;
381 
382       for (tpenv = (ENV_t FAR *) genv->henv;
383 	  tpenv != NULL;
384 	  tpenv = (ENV_t FAR *) penv->next)
385 	{
386 	  if (tpenv == penv)
387 	    {
388 	      genv->henv = penv->next;
389 	      break;
390 	    }
391 
392 	  if (tpenv->next == penv)
393 	    {
394 	      tpenv->next = penv->next;
395 	      break;
396 	    }
397 	}
398 
399       MEM_FREE (penv);
400     }
401 
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;
408 
409   /* set connect options to default values */
410 	/**********
411 	pdbc->access_mode	= SQL_MODE_DEFAULT;
412 	pdbc->autocommit	= SQL_AUTOCOMMIT_DEFAULT;
413 	pdbc->login_timeout 	= 0UL;
414 	**********/
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;
419 
420   if (pdbc->current_qualifier != NULL)
421     {
422       MEM_FREE (pdbc->current_qualifier);
423       pdbc->current_qualifier = NULL;
424     }
425 
426   return SQL_SUCCESS;
427 }
428 
429 
430 static RETCODE
_iodbcdm_dbcdelayset(HDBC hdbc)431 _iodbcdm_dbcdelayset (HDBC hdbc)
432 {
433   DBC_t FAR *pdbc = (DBC_t FAR *) hdbc;
434   ENV_t FAR *penv;
435   HPROC hproc;
436   RETCODE retcode = SQL_SUCCESS;
437   RETCODE ret;
438 
439   penv = pdbc->henv;
440 
441   hproc = _iodbcdm_getproc (hdbc, en_SetConnectOption);
442 
443   if (hproc == SQL_NULL_HPROC)
444     {
445       PUSHSQLERR (pdbc->herr, en_IM006);
446 
447       return SQL_SUCCESS_WITH_INFO;
448     }
449 
450   if (pdbc->access_mode != SQL_MODE_DEFAULT)
451     {
452       CALL_DRIVER (hdbc, ret, hproc,
453 	  en_SetConnectOption, (
454 	      SQL_ACCESS_MODE,
455 	      pdbc->access_mode))
456 
457 	  retcode |= ret;
458     }
459 
460   if (pdbc->autocommit != SQL_AUTOCOMMIT_DEFAULT)
461     {
462       CALL_DRIVER (hdbc, ret, hproc,
463 	  en_SetConnectOption, (
464 	      pdbc->dhdbc,
465 	      SQL_AUTOCOMMIT,
466 	      pdbc->autocommit))
467 
468 	  retcode |= ret;
469     }
470 
471   if (pdbc->current_qualifier != NULL)
472     {
473       CALL_DRIVER (hdbc, ret, hproc,
474 	  en_SetConnectOption, (
475 	      pdbc->dhdbc,
476 	      SQL_CURRENT_QUALIFIER,
477 	      pdbc->current_qualifier))
478 
479 	  retcode |= ret;
480     }
481 
482   if (pdbc->packet_size != 0UL)
483     {
484       CALL_DRIVER (hdbc, ret, hproc,
485 	  en_SetConnectOption, (
486 	      pdbc->dhdbc,
487 	      SQL_PACKET_SIZE,
488 	      pdbc->packet_size))
489 
490 	  retcode |= ret;
491     }
492 
493   if (pdbc->quiet_mode != (UDWORD) NULL)
494     {
495       CALL_DRIVER (hdbc, ret, hproc,
496 	  en_SetConnectOption, (
497 	      pdbc->dhdbc,
498 	      SQL_QUIET_MODE,
499 	      pdbc->quiet_mode))
500 
501 	  retcode |= ret;
502     }
503 
504   if (pdbc->txn_isolation != SQL_TXN_READ_UNCOMMITTED)
505     {
506       CALL_DRIVER (hdbc, ret, hproc,
507 	  en_SetConnectOption, (
508 	      pdbc->dhdbc,
509 	      SQL_TXN_ISOLATION,
510 	      pdbc->txn_isolation))
511     }
512 
513   /* check error code for driver's SQLSetConnectOption() call */
514   if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
515     {
516       PUSHSQLERR (pdbc->herr, en_IM006);
517 
518       retcode = SQL_ERROR;
519     }
520 
521   /* get cursor behavior on transaction commit or rollback */
522   hproc = _iodbcdm_getproc (hdbc, en_GetInfo);
523 
524   if (hproc == SQL_NULL_HPROC)
525     {
526       PUSHSQLERR (pdbc->herr, en_01000);
527 
528       return retcode;
529     }
530 
531   CALL_DRIVER (hdbc, ret, hproc,
532       en_GetInfo, (
533 	  pdbc->dhdbc,
534 	  SQL_CURSOR_COMMIT_BEHAVIOR,
535 	  (PTR) & (pdbc->cb_commit),
536 	  sizeof (pdbc->cb_commit),
537 	  NULL))
538 
539       retcode |= ret;
540 
541   CALL_DRIVER (hdbc, ret, hproc,
542       en_GetInfo, (
543 	  pdbc->dhdbc,
544 	  SQL_CURSOR_ROLLBACK_BEHAVIOR,
545 	  (PTR) & (pdbc->cb_rollback),
546 	  sizeof (pdbc->cb_rollback),
547 	  NULL))
548 
549       retcode |= ret;
550 
551   if (retcode != SQL_SUCCESS
552       && retcode != SQL_SUCCESS_WITH_INFO)
553     {
554       return SQL_ERROR;
555     }
556 
557   return retcode;
558 }
559 
560 
561 static RETCODE
_iodbcdm_settracing(HDBC hdbc,char * dsn,int dsnlen)562 _iodbcdm_settracing (HDBC hdbc, char *dsn, int dsnlen)
563 {
564   char buf[256];
565   char *ptr;
566   RETCODE setopterr = SQL_SUCCESS;
567 
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));
571 
572   if (ptr == NULL || ptr[0] == '\0')
573     {
574       ptr = (char FAR *) (SQL_OPT_TRACE_FILE_DEFAULT);
575     }
576 
577   setopterr |= SQLSetConnectOption (hdbc, SQL_OPT_TRACEFILE, (UDWORD) (ptr));
578 
579   ptr = _iodbcdm_getkeyvalbydsn (dsn, dsnlen, "Trace",
580       (char FAR *) buf, sizeof (buf));
581 
582   if (ptr != NULL)
583     {
584       UDWORD opt = (UDWORD) (-1L);
585 
586       if (STREQ (ptr, "ON")
587 	  || STREQ (ptr, "On")
588 	  || STREQ (ptr, "on")
589 	  || STREQ (ptr, "1"))
590 	{
591 	  opt = SQL_OPT_TRACE_ON;
592 	}
593 
594       if (STREQ (ptr, "OFF")
595 	  || STREQ (ptr, "Off")
596 	  || STREQ (ptr, "off")
597 	  || STREQ (ptr, "0"))
598 	{
599 	  opt = SQL_OPT_TRACE_OFF;
600 	}
601 
602       if (opt != (UDWORD) (-1L))
603 	{
604 	  setopterr |= SQLSetConnectOption (hdbc,
605 	      SQL_OPT_TRACE, opt);
606 	}
607     }
608 
609   return setopterr;
610 }
611 
612 
613 RETCODE SQL_API
SQLConnect(HDBC hdbc,UCHAR FAR * szDSN,SWORD cbDSN,UCHAR FAR * szUID,SWORD cbUID,UCHAR FAR * szAuthStr,SWORD cbAuthStr)614 SQLConnect (
615     HDBC hdbc,
616     UCHAR FAR * szDSN,
617     SWORD cbDSN,
618     UCHAR FAR * szUID,
619     SWORD cbUID,
620     UCHAR FAR * szAuthStr,
621     SWORD cbAuthStr)
622 {
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
627 				 * specifies driver
628 				 * path can't longer
629 				 * than 255. */
630   char *ptr;
631   HPROC hproc;
632 
633   if (hdbc == SQL_NULL_HDBC)
634     {
635       return SQL_INVALID_HANDLE;
636     }
637 
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))
643     {
644       PUSHSQLERR (pdbc->herr, en_S1090);
645 
646       return SQL_ERROR;
647     }
648 
649   if (szDSN == NULL || cbDSN == 0)
650     {
651       PUSHSQLERR (pdbc->herr, en_IM002);
652 
653       return SQL_ERROR;
654     }
655 
656   /* check state */
657   if (pdbc->state != en_dbc_allocated)
658     {
659       PUSHSQLERR (pdbc->herr, en_08002);
660 
661       return SQL_ERROR;
662     }
663 
664   setopterr |= _iodbcdm_settracing (hdbc,
665       (char *) szDSN, cbDSN);
666 
667   ptr = _iodbcdm_getkeyvalbydsn (szDSN, cbDSN, "Driver",
668       (char FAR *) driver, sizeof (driver));
669 
670   if (ptr == NULL)
671     /* No specified or default dsn section or
672      * no driver specification in this dsn section */
673     {
674       PUSHSQLERR (pdbc->herr, en_IM002);
675 
676       return SQL_ERROR;
677     }
678 
679   retcode = _iodbcdm_driverload (driver, hdbc);
680 
681   switch (retcode)
682      {
683      case SQL_SUCCESS:
684        break;
685 
686      case SQL_SUCCESS_WITH_INFO:
687        setopterr = SQL_ERROR;
688        /* unsuccessed in calling driver's
689         * SQLSetConnectOption() to set login
690         * timeout.
691         */
692        break;
693 
694      default:
695        return retcode;
696      }
697 
698   hproc = _iodbcdm_getproc (hdbc, en_Connect);
699 
700   if (hproc == SQL_NULL_HPROC)
701     {
702       _iodbcdm_driverunload (hdbc);
703 
704       PUSHSQLERR (pdbc->herr, en_IM001);
705 
706       return SQL_ERROR;
707     }
708 
709   CALL_DRIVER (hdbc, retcode, hproc, en_Connect, (
710 	  pdbc->dhdbc,
711 	  szDSN, cbDSN,
712 	  szUID, cbUID,
713 	  szAuthStr, cbAuthStr))
714 
715   if (retcode != SQL_SUCCESS
716       && retcode != SQL_SUCCESS_WITH_INFO)
717     {
718       /* not unload driver for retrive error
719        * messge from driver */
720 		/*********
721 		_iodbcdm_driverunload( hdbc );
722 		**********/
723 
724       return retcode;
725     }
726 
727   /* state transition */
728   pdbc->state = en_dbc_connected;
729 
730   /* do delaid option setting */
731   setopterr |= _iodbcdm_dbcdelayset (hdbc);
732 
733   if (setopterr != SQL_SUCCESS)
734     {
735       return SQL_SUCCESS_WITH_INFO;
736     }
737 
738   return retcode;
739 }
740 
741 
742 RETCODE SQL_API
SQLDriverConnect(HDBC hdbc,SQLHWND hwnd,UCHAR FAR * szConnStrIn,SWORD cbConnStrIn,UCHAR FAR * szConnStrOut,SWORD cbConnStrOutMax,SWORD FAR * pcbConnStrOut,UWORD fDriverCompletion)743 SQLDriverConnect (
744     HDBC hdbc,
745     SQLHWND hwnd,
746     UCHAR FAR * szConnStrIn,
747     SWORD cbConnStrIn,
748     UCHAR FAR * szConnStrOut,
749     SWORD cbConnStrOutMax,
750     SWORD FAR * pcbConnStrOut,
751     UWORD fDriverCompletion)
752 {
753   DBC_t FAR *pdbc = (DBC_t FAR *) hdbc;
754   HDLL hdll;
755   char FAR *drv;
756   char drvbuf[1024];
757   char FAR *dsn;
758   char dsnbuf[SQL_MAX_DSN_LENGTH + 1];
759   UCHAR cnstr2drv[1024];
760 
761   HPROC hproc;
762   HPROC dialproc;
763 
764   int sqlstat = en_00000;
765   RETCODE retcode = SQL_SUCCESS;
766   RETCODE setopterr = SQL_SUCCESS;
767 
768   if (hdbc == SQL_NULL_HDBC)
769     {
770       return SQL_INVALID_HANDLE;
771     }
772 
773   /* check arguments */
774   if ((cbConnStrIn < 0 && cbConnStrIn != SQL_NTS)
775       || cbConnStrOutMax < 0)
776     {
777       PUSHSQLERR (pdbc->herr, en_S1090);
778 
779       return SQL_ERROR;
780     }
781 
782   /* check state */
783   if (pdbc->state != en_dbc_allocated)
784     {
785       PUSHSQLERR (pdbc->herr, en_08002);
786 
787       return SQL_ERROR;
788     }
789 
790   drv = _iodbcdm_getkeyvalinstr (szConnStrIn, cbConnStrIn,
791       "DRIVER", drvbuf, sizeof (drvbuf));
792 
793   dsn = _iodbcdm_getkeyvalinstr (szConnStrIn, cbConnStrIn,
794       "DSN", dsnbuf, sizeof (dsnbuf));
795 
796   switch (fDriverCompletion)
797      {
798      case SQL_DRIVER_NOPROMPT:
799        break;
800 
801      case SQL_DRIVER_COMPLETE:
802      case SQL_DRIVER_COMPLETE_REQUIRED:
803        if (dsn != NULL || drv != NULL)
804 	 {
805 	   break;
806 	 }
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");
814 
815        if (dialproc == SQL_NULL_HPROC)
816 	 {
817 	   sqlstat = en_IM008;
818 	   break;
819 	 }
820 
821        retcode = dialproc (
822 	   hwnd,		/* window or display handle */
823 	   dsnbuf,		/* input/output dsn buf */
824 	   sizeof (dsnbuf),	/* buf size */
825 	   &sqlstat);		/* error code */
826 
827        if (retcode != SQL_SUCCESS)
828 	 {
829 	   break;
830 	 }
831 
832        if (cbConnStrIn == SQL_NTS)
833 	 {
834 	   cbConnStrIn = STRLEN (szConnStrIn);
835 	 }
836 
837        dsn = dsnbuf;
838 
839        if (dsn[0] == '\0')
840 	 {
841 	   dsn = "default";
842 	 }
843 
844        if (cbConnStrIn > sizeof (cnstr2drv)
845 	   - STRLEN (dsn) - STRLEN ("DSN=;") - 1)
846 	 {
847 	   sqlstat = en_S1001;	/* a lazy way to avoid
848 				 * using heap memory */
849 	   break;
850 	 }
851 
852        sprintf ((char*)cnstr2drv, "DSN=%s;", dsn);
853        cbConnStrIn += STRLEN (cnstr2drv);
854        STRNCAT (cnstr2drv, szConnStrIn, cbConnStrIn);
855        szConnStrIn = cnstr2drv;
856        break;
857 
858      default:
859        sqlstat = en_S1110;
860        break;
861      }
862 
863   if (sqlstat != en_00000)
864     {
865       PUSHSQLERR (pdbc->herr, sqlstat);
866 
867       return SQL_ERROR;
868     }
869 
870   if (dsn == NULL || dsn[0] == '\0')
871     {
872       dsn = "default";
873     }
874   else
875     /* if you want tracing, you must use a DSN */
876     {
877       setopterr |= _iodbcdm_settracing (hdbc,
878 	  (char *) dsn, SQL_NTS);
879     }
880 
881   if (drv == NULL || drv[0] == '\0')
882     {
883       drv = _iodbcdm_getkeyvalbydsn (dsn, SQL_NTS, "Driver",
884 	  drvbuf, sizeof (drvbuf));
885     }
886 
887   if (drv == NULL)
888     {
889       PUSHSQLERR (pdbc->herr, en_IM002);
890 
891       return SQL_ERROR;
892     }
893 
894   retcode = _iodbcdm_driverload (drv, hdbc);
895 
896   switch (retcode)
897      {
898      case SQL_SUCCESS:
899        break;
900 
901      case SQL_SUCCESS_WITH_INFO:
902        setopterr = SQL_ERROR;
903        /* unsuccessed in calling driver's
904         * SQLSetConnectOption() to set login
905         * timeout.
906         */
907        break;
908 
909      default:
910        return retcode;
911      }
912 
913   hproc = _iodbcdm_getproc (hdbc, en_DriverConnect);
914 
915   if (hproc == SQL_NULL_HPROC)
916     {
917       _iodbcdm_driverunload (hdbc);
918 
919       PUSHSQLERR (pdbc->herr, en_IM001);
920 
921       return SQL_ERROR;
922     }
923 
924   CALL_DRIVER (hdbc, retcode, hproc, en_DriverConnect, (
925 	  pdbc->dhdbc, hwnd,
926 	  szConnStrIn, cbConnStrIn,
927 	  szConnStrOut, cbConnStrOutMax,
928 	  pcbConnStrOut, fDriverCompletion))
929 
930   if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
931     {
932       /* don't unload driver here for retrive
933        * error message from driver */
934 		/********
935 		_iodbcdm_driverunload( hdbc );
936 		*********/
937 
938       return retcode;
939     }
940 
941   /* state transition */
942   pdbc->state = en_dbc_connected;
943 
944   /* do delaid option setting */
945   setopterr |= _iodbcdm_dbcdelayset (hdbc);
946 
947   if (setopterr != SQL_SUCCESS)
948     {
949       return SQL_SUCCESS_WITH_INFO;
950     }
951 
952   return retcode;
953 }
954 
955 
956 RETCODE SQL_API
SQLBrowseConnect(HDBC hdbc,UCHAR FAR * szConnStrIn,SWORD cbConnStrIn,UCHAR FAR * szConnStrOut,SWORD cbConnStrOutMax,SWORD FAR * pcbConnStrOut)957 SQLBrowseConnect (
958     HDBC hdbc,
959     UCHAR FAR * szConnStrIn,
960     SWORD cbConnStrIn,
961     UCHAR FAR * szConnStrOut,
962     SWORD cbConnStrOutMax,
963     SWORD FAR * pcbConnStrOut)
964 {
965   DBC_t FAR *pdbc = (DBC_t FAR *) hdbc;
966   char FAR *drv;
967   char drvbuf[1024];
968   char FAR *dsn;
969   char dsnbuf[SQL_MAX_DSN_LENGTH + 1];
970 
971   HPROC hproc;
972 
973   RETCODE retcode = SQL_SUCCESS;
974   RETCODE setopterr = SQL_SUCCESS;
975 
976   if (hdbc == SQL_NULL_HDBC)
977     {
978       return SQL_INVALID_HANDLE;
979     }
980 
981   /* check arguments */
982   if ((cbConnStrIn < 0 && cbConnStrIn != SQL_NTS) || cbConnStrOutMax < 0)
983     {
984       PUSHSQLERR (pdbc->herr, en_S1090);
985 
986       return SQL_ERROR;
987     }
988 
989   if (pdbc->state == en_dbc_allocated)
990     {
991       drv = _iodbcdm_getkeyvalinstr (szConnStrIn, cbConnStrIn,
992 	  "DRIVER", drvbuf, sizeof (drvbuf));
993 
994       dsn = _iodbcdm_getkeyvalinstr (szConnStrIn, cbConnStrIn,
995 	  "DSN", dsnbuf, sizeof (dsnbuf));
996 
997       if (dsn == NULL || dsn[0] == '\0')
998 	{
999 	  dsn = "default";
1000 	}
1001       else
1002 	/* if you want tracing, you must use a DSN */
1003 	{
1004 	  setopterr |= _iodbcdm_settracing (hdbc,
1005 	      (char *) dsn, SQL_NTS);
1006 	}
1007 
1008       if (drv == NULL || drv[0] == '\0')
1009 	{
1010 	  drv = _iodbcdm_getkeyvalbydsn (dsn, SQL_NTS, "Driver",
1011 	      drvbuf, sizeof (drvbuf));
1012 	}
1013 
1014       if (drv == NULL)
1015 	{
1016 	  PUSHSQLERR (pdbc->herr, en_IM002);
1017 
1018 	  return SQL_ERROR;
1019 	}
1020 
1021       retcode = _iodbcdm_driverload (drv, hdbc);
1022 
1023       switch (retcode)
1024 	 {
1025 	 case SQL_SUCCESS:
1026 	   break;
1027 
1028 	 case SQL_SUCCESS_WITH_INFO:
1029 	   setopterr = SQL_ERROR;
1030 	   /* unsuccessed in calling driver's
1031 	    * SQLSetConnectOption() to set login
1032 	    * timeout.
1033 	    */
1034 	   break;
1035 
1036 	 default:
1037 	   return retcode;
1038 	 }
1039     }
1040   else if (pdbc->state != en_dbc_needdata)
1041     {
1042       PUSHSQLERR (pdbc->herr, en_08002);
1043 
1044       return SQL_ERROR;
1045     }
1046 
1047   hproc = _iodbcdm_getproc (hdbc, en_BrowseConnect);
1048 
1049   if (hproc == SQL_NULL_HPROC)
1050     {
1051       _iodbcdm_driverunload (hdbc);
1052 
1053       pdbc->state = en_dbc_allocated;
1054 
1055       PUSHSQLERR (pdbc->herr, en_IM001);
1056 
1057       return SQL_ERROR;
1058     }
1059 
1060   CALL_DRIVER (hdbc, retcode, hproc, en_BrowseConnect, (
1061 	  pdbc->dhdbc,
1062 	  szConnStrIn, cbConnStrIn,
1063 	  szConnStrOut, cbConnStrOutMax,
1064 	  pcbConnStrOut))
1065 
1066   switch (retcode)
1067      {
1068      case SQL_SUCCESS:
1069      case SQL_SUCCESS_WITH_INFO:
1070        pdbc->state = en_dbc_connected;
1071        setopterr |= _iodbcdm_dbcdelayset (hdbc);
1072        if (setopterr != SQL_SUCCESS)
1073 	 {
1074 	   retcode = SQL_SUCCESS_WITH_INFO;
1075 	 }
1076        break;
1077 
1078      case SQL_NEED_DATA:
1079        pdbc->state = en_dbc_needdata;
1080        break;
1081 
1082      case SQL_ERROR:
1083        pdbc->state = en_dbc_allocated;
1084        /* but the driver will not unloaded
1085         * to allow application retrive err
1086         * message from driver
1087         */
1088        break;
1089 
1090      default:
1091        break;
1092      }
1093 
1094   return retcode;
1095 }
1096 
1097 
1098 RETCODE SQL_API
SQLDisconnect(HDBC hdbc)1099 SQLDisconnect (HDBC hdbc)
1100 {
1101   DBC_t FAR *pdbc = (DBC_t *) hdbc;
1102   STMT_t FAR *pstmt;
1103   RETCODE retcode;
1104   HPROC hproc;
1105 
1106   int sqlstat = en_00000;
1107 
1108   if (hdbc == SQL_NULL_HDBC)
1109     {
1110       return SQL_INVALID_HANDLE;
1111     }
1112 
1113   /* check hdbc state */
1114   if (pdbc->state == en_dbc_allocated)
1115     {
1116       sqlstat = en_08003;
1117     }
1118 
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)
1123     {
1124       if (pstmt->state >= en_stmt_needdata
1125 	  || pstmt->asyn_on != en_NullProc)
1126 	/* In this case one need to call
1127 	 * SQLCancel() first */
1128 	{
1129 	  sqlstat = en_S1010;
1130 	}
1131     }
1132 
1133   if (sqlstat == en_00000)
1134     {
1135       hproc = _iodbcdm_getproc (hdbc, en_Disconnect);
1136 
1137       if (hproc == SQL_NULL_HPROC)
1138 	{
1139 	  sqlstat = en_IM001;
1140 	}
1141     }
1142 
1143   if (sqlstat != en_00000)
1144     {
1145       PUSHSQLERR (pdbc->herr, sqlstat);
1146 
1147       return SQL_ERROR;
1148     }
1149 
1150   CALL_DRIVER (hdbc, retcode, hproc, en_Disconnect, (
1151 	  pdbc->dhdbc))
1152 
1153   if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
1154     {
1155       /* diff from MS specs. We disallow
1156        * driver SQLDisconnect() return
1157        * SQL_SUCCESS_WITH_INFO and post
1158        * error message.
1159        */
1160       retcode = SQL_SUCCESS;
1161     }
1162   else
1163     {
1164       return retcode;
1165     }
1166 
1167   /* free all statement handle(s) on this connection */
1168   for (; pdbc->hstmt;)
1169     {
1170       _iodbcdm_dropstmt (pdbc->hstmt);
1171     }
1172 
1173   /* state transition */
1174   if (retcode == SQL_SUCCESS)
1175     {
1176       pdbc->state = en_dbc_allocated;
1177     }
1178 
1179   return retcode;
1180 }
1181 
1182 
1183 RETCODE SQL_API
SQLNativeSql(HDBC hdbc,UCHAR FAR * szSqlStrIn,SDWORD cbSqlStrIn,UCHAR FAR * szSqlStr,SDWORD cbSqlStrMax,SDWORD FAR * pcbSqlStr)1184 SQLNativeSql (
1185     HDBC hdbc,
1186     UCHAR FAR * szSqlStrIn,
1187     SDWORD cbSqlStrIn,
1188     UCHAR FAR * szSqlStr,
1189     SDWORD cbSqlStrMax,
1190     SDWORD FAR * pcbSqlStr)
1191 {
1192   DBC_t FAR *pdbc = (DBC_t FAR *) hdbc;
1193   HPROC hproc;
1194   int sqlstat = en_00000;
1195   RETCODE retcode;
1196 
1197   if (hdbc == SQL_NULL_HDBC)
1198     {
1199       return SQL_INVALID_HANDLE;
1200     }
1201 
1202   /* check argument */
1203   if (szSqlStrIn == NULL)
1204     {
1205       sqlstat = en_S1009;
1206     }
1207   else if (cbSqlStrIn < 0 && cbSqlStrIn != SQL_NTS)
1208     {
1209       sqlstat = en_S1090;
1210     }
1211 
1212   if (sqlstat != en_00000)
1213     {
1214       PUSHSQLERR (pdbc->herr, sqlstat);
1215 
1216       return SQL_ERROR;
1217     }
1218 
1219   /* check state */
1220   if (pdbc->state <= en_dbc_needdata)
1221     {
1222       PUSHSQLERR (pdbc->herr, en_08003);
1223 
1224       return SQL_ERROR;
1225     }
1226 
1227   /* call driver */
1228   hproc = _iodbcdm_getproc (hdbc, en_NativeSql);
1229 
1230   if (hproc == SQL_NULL_HPROC)
1231     {
1232       PUSHSQLERR (pdbc->herr, en_IM001);
1233 
1234       return SQL_ERROR;
1235     }
1236 
1237   CALL_DRIVER (hdbc, retcode, hproc, en_NativeSql,
1238     (pdbc->dhdbc, szSqlStrIn, cbSqlStrIn, szSqlStr, cbSqlStrMax, pcbSqlStr))
1239 
1240   return retcode;
1241 }
1242