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