new makefiles (part I)
[wxWidgets.git] / src / iodbc / connect.c
1 /*
2 * connect.c
3 *
4 * $Id$
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
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
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
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
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
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
743 SQLDriverConnect (
744 HDBC hdbc,
745 HWND 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 (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
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
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
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 }