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 41extern char* _iodbcdm_getkeyvalbydsn(); 42extern char* _iodbcdm_getkeyvalinstr(); 43extern 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 */ 52static 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 */ 62static 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 */ 302RETCODE 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 430static 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 561static 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 613RETCODE SQL_API 614SQLConnect ( 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 742RETCODE SQL_API 743SQLDriverConnect ( 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 956RETCODE SQL_API 957SQLBrowseConnect ( 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 1098RETCODE SQL_API 1099SQLDisconnect (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 1183RETCODE SQL_API 1184SQLNativeSql ( 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