1/*********************************************************************
2 *
3 * This is based on code created by Peter Harvey,
4 * (pharvey@codebydesign.com).
5 *
6 * Modified and extended by Nick Gorham
7 * (nick@lurcher.org).
8 *
9 * Any bugs or problems should be considered the fault of Nick and not
10 * Peter.
11 *
12 * copyright (c) 1999 Nick Gorham
13 *
14 * This library is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU Lesser General Public
16 * License as published by the Free Software Foundation; either
17 * version 2 of the License, or (at your option) any later version.
18 *
19 * This library is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * Lesser General Public License for more details.
23 *
24 * You should have received a copy of the GNU Lesser General Public
25 * License along with this library; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 *
28 **********************************************************************
29 *
30 * $Id: SQLDriverConnectW.c,v 1.18 2009/02/18 17:59:08 lurcher Exp $
31 *
32 * $Log: SQLDriverConnectW.c,v $
33 * Revision 1.18 2009/02/18 17:59:08 lurcher
34 * Shift to using config.h, the compile lines were making it hard to spot warnings
35 *
36 * Revision 1.17 2009/01/16 11:02:38 lurcher
37 * Interface to GUI for DSN selection
38 *
39 * Revision 1.16 2009/01/12 15:18:15 lurcher
40 * Add interface into odbcinstQ to allow for a dialog if SQLDriverConnect is called without a DSN=
41 *
42 * Revision 1.15 2008/09/29 14:02:44 lurcher
43 * Fix missing dlfcn group option
44 *
45 * Revision 1.14 2007/02/28 15:37:47 lurcher
46 * deal with drivers that call internal W functions and end up in the driver manager. controlled by the --enable-handlemap configure arg
47 *
48 * Revision 1.13 2003/10/30 18:20:45 lurcher
49 *
50 * Fix broken thread protection
51 * Remove SQLNumResultCols after execute, lease S4/S% to driver
52 * Fix string overrun in SQLDriverConnect
53 * Add initial support for Interix
54 *
55 * Revision 1.12 2003/08/08 11:14:21 lurcher
56 *
57 * Fix UNICODE problem in SQLDriverConnectW
58 *
59 * Revision 1.11 2002/12/20 11:36:46 lurcher
60 *
61 * Update DMEnvAttr code to allow setting in the odbcinst.ini entry
62 *
63 * Revision 1.10 2002/12/05 17:44:30 lurcher
64 *
65 * Display unknown return values in return logging
66 *
67 * Revision 1.9 2002/10/14 09:46:10 lurcher
68 *
69 * Remove extra return
70 *
71 * Revision 1.8 2002/07/25 09:30:26 lurcher
72 *
73 * Additional unicode and iconv changes
74 *
75 * Revision 1.7 2002/07/24 08:49:51 lurcher
76 *
77 * Alter UNICODE support to use iconv for UNICODE-ANSI conversion
78 *
79 * Revision 1.6 2002/07/04 17:27:56 lurcher
80 *
81 * Small bug fixes
82 *
83 * Revision 1.4 2002/05/24 12:42:50 lurcher
84 *
85 * Alter NEWS and ChangeLog to match their correct usage
86 * Additional UNICODE tweeks
87 *
88 * Revision 1.3 2002/01/21 18:00:51 lurcher
89 *
90 * Assorted fixed and changes, mainly UNICODE/bug fixes
91 *
92 * Revision 1.2 2001/12/13 13:00:32 lurcher
93 *
94 * Remove most if not all warnings on 64 bit platforms
95 * Add support for new MS 3.52 64 bit changes
96 * Add override to disable the stopping of tracing
97 * Add MAX_ROWS support in postgres driver
98 *
99 * Revision 1.1.1.1 2001/10/17 16:40:05 lurcher
100 *
101 * First upload to SourceForge
102 *
103 * Revision 1.5 2001/05/15 10:57:44 nick
104 *
105 * Add initial support for VMS
106 *
107 * Revision 1.4 2001/04/16 15:41:24 nick
108 *
109 * Fix some problems calling non existing error funcs
110 *
111 * Revision 1.3 2001/04/12 17:43:36 nick
112 *
113 * Change logging and added autotest to odbctest
114 *
115 * Revision 1.2 2001/01/03 11:57:27 nick
116 *
117 * Fix some name collisions
118 *
119 * Revision 1.1 2000/12/31 20:30:54 nick
120 *
121 * Add UNICODE support
122 *
123 *
124 **********************************************************************/
125
126#include <config.h>
127#include <string.h>
128#include "drivermanager.h"
129
130static char const rcsid[]= "$RCSfile: SQLDriverConnectW.c,v $";
131
132int __parse_connection_string_w( struct con_struct *con_str,
133 SQLWCHAR *str, int str_len )
134{
135struct con_pair *cp;
136char *local_str, *ptr;
137int len;
138int got_dsn = 0; /* if we have a DSN then ignore any DRIVER or FILEDSN */
139int got_driver = 0; /* if we have a DRIVER or FILEDSN then ignore any DSN */
140
141 con_str -> count = 0;
142 con_str -> list = NULL;
143
144 if ( str_len == SQL_NTS )
145 {
146 len = wide_strlen( str );
147 local_str = malloc( len + 1 );
148 }
149 else
150 {
151 len = str_len;
152 local_str = malloc( len + 1 );
153 }
154
155 unicode_to_ansi_copy( local_str, len+1, str, len, NULL, NULL );
156
157 if ( !local_str || strlen( local_str ) == 0 ||
158 ( strlen( local_str ) == 1 && *local_str == ';' ))
159 {
160 /* connection-string ::= empty-string [;] */
161 free( local_str );
162 return 0;
163 }
164
165 ptr = local_str;
166
167 while(( cp = __get_pair( &ptr )) != NULL )
168 {
169 if ( strcasecmp( cp -> keyword, "DSN" ) == 0 )
170 {
171 if ( got_driver )
172 continue;
173
174 got_dsn = 1;
175 }
176 else if ( strcasecmp( cp -> keyword, "DRIVER" ) == 0 ||
177 strcasecmp( cp -> keyword, "FILEDSN" ) == 0 )
178 {
179 if ( got_dsn )
180 continue;
181
182 got_driver = 1;
183 }
184
185 __append_pair( con_str, cp -> keyword, cp -> attribute );
186 free( cp -> keyword );
187 free( cp -> attribute );
188 free( cp );
189 }
190
191 free( local_str );
192
193 return 0;
194}
195
196SQLRETURN SQLDriverConnectW(
197 SQLHDBC hdbc,
198 SQLHWND hwnd,
199 SQLWCHAR *conn_str_in,
200 SQLSMALLINT len_conn_str_in,
201 SQLWCHAR *conn_str_out,
202 SQLSMALLINT conn_str_out_max,
203 SQLSMALLINT *ptr_conn_str_out,
204 SQLUSMALLINT driver_completion )
205{
206 DMHDBC connection = (DMHDBC)hdbc;
207 struct con_struct con_struct;
208 char *driver = NULL, *dsn = NULL;
209 char lib_name[ INI_MAX_PROPERTY_VALUE + 1 ];
210 char driver_name[ INI_MAX_PROPERTY_VALUE + 1 ];
211 SQLWCHAR local_conn_string[ 1024 ];
212 SQLCHAR local_conn_str_in[ 1024 ];
213 SQLRETURN ret_from_connect;
214 SQLCHAR s1[ 2048 ];
215 int warnings = 0;
216
217 /*
218 * check connection
219 */
220
221 strcpy( driver_name, "" );
222
223 if ( !__validate_dbc( connection ))
224 {
225 dm_log_write( __FILE__,
226 __LINE__,
227 LOG_INFO,
228 LOG_INFO,
229 "Error: SQL_INVALID_HANDLE" );
230
231#ifdef WITH_HANDLE_REDIRECT
232 {
233 DMHDBC parent_connection;
234
235 parent_connection = find_parent_handle( connection, SQL_HANDLE_DBC );
236
237 if ( parent_connection ) {
238 dm_log_write( __FILE__,
239 __LINE__,
240 LOG_INFO,
241 LOG_INFO,
242 "Info: found parent handle" );
243
244 if ( CHECK_SQLDRIVERCONNECTW( parent_connection ))
245 {
246 dm_log_write( __FILE__,
247 __LINE__,
248 LOG_INFO,
249 LOG_INFO,
250 "Info: calling redirected driver function" );
251
252 return SQLDRIVERCONNECTW( parent_connection,
253 connection,
254 hwnd,
255 conn_str_in,
256 len_conn_str_in,
257 conn_str_out,
258 conn_str_out_max,
259 ptr_conn_str_out,
260 driver_completion );
261 }
262 }
263 }
264#endif
265 return SQL_INVALID_HANDLE;
266 }
267
268 function_entry( connection );
269
270 if ( log_info.log_flag )
271 {
272 sprintf( connection -> msg, "\n\t\tEntry:\
273\n\t\t\tConnection = %p\
274\n\t\t\tWindow Hdl = %p\
275\n\t\t\tStr In = %s\
276\n\t\t\tStr Out = %p\
277\n\t\t\tStr Out Max = %d\
278\n\t\t\tStr Out Ptr = %p\
279\n\t\t\tCompletion = %d",
280 connection,
281 hwnd,
282 __wstring_with_length_hide_pwd( s1, conn_str_in,
283 len_conn_str_in ),
284 conn_str_out,
285 conn_str_out_max,
286 ptr_conn_str_out,
287 driver_completion );
288
289 dm_log_write( __FILE__,
290 __LINE__,
291 LOG_INFO,
292 LOG_INFO,
293 connection -> msg );
294 }
295
296 thread_protect( SQL_HANDLE_DBC, connection );
297
298 if ( len_conn_str_in < 0 && len_conn_str_in != SQL_NTS )
299 {
300 dm_log_write( __FILE__,
301 __LINE__,
302 LOG_INFO,
303 LOG_INFO,
304 "Error: HY090" );
305
306 __post_internal_error( &connection -> error,
307 ERROR_HY090, NULL,
308 connection -> environment -> requested_version );
309
310 return function_return( SQL_HANDLE_DBC, connection, SQL_ERROR );
311 }
312
313 if ( driver_completion == SQL_DRIVER_PROMPT &&
314 hwnd == NULL )
315 {
316 dm_log_write( __FILE__,
317 __LINE__,
318 LOG_INFO,
319 LOG_INFO,
320 "Error: HY092" );
321
322 __post_internal_error( &connection -> error,
323 ERROR_HY092, NULL,
324 connection -> environment -> requested_version );
325
326 return function_return( SQL_HANDLE_DBC, connection, SQL_ERROR );
327 }
328
329 if ( driver_completion != SQL_DRIVER_PROMPT &&
330 driver_completion != SQL_DRIVER_COMPLETE &&
331 driver_completion != SQL_DRIVER_COMPLETE_REQUIRED &&
332 driver_completion != SQL_DRIVER_NOPROMPT )
333 {
334 dm_log_write( __FILE__,
335 __LINE__,
336 LOG_INFO,
337 LOG_INFO,
338 "Error: HY110" );
339
340 __post_internal_error( &connection -> error,
341 ERROR_HY110, NULL,
342 connection -> environment -> requested_version );
343
344 return function_return( SQL_HANDLE_DBC, connection, SQL_ERROR );
345 }
346
347 /*
348 * check the state of the connection
349 */
350
351 if ( connection -> state != STATE_C2 )
352 {
353 dm_log_write( __FILE__,
354 __LINE__,
355 LOG_INFO,
356 LOG_INFO,
357 "Error: 08002" );
358
359 __post_internal_error( &connection -> error,
360 ERROR_08002, NULL,
361 connection -> environment -> requested_version );
362
363 return function_return( SQL_HANDLE_DBC, connection, SQL_ERROR );
364 }
365
366 /*
367 * parse the connection string
368 */
369
370 if ( driver_completion == SQL_DRIVER_NOPROMPT )
371 {
372 char *ansi_conn_str_in;
373
374 if ( !conn_str_in )
375 {
376 ansi_conn_str_in = "DSN=DEFAULT;";
377 len_conn_str_in = strlen( ansi_conn_str_in );
378
379 ansi_to_unicode_copy( local_conn_string, ansi_conn_str_in, len_conn_str_in, connection, NULL );
380 conn_str_in = local_conn_string;
381
382 __parse_connection_string( &con_struct,
383 ansi_conn_str_in, len_conn_str_in );
384 }
385 else
386 {
387 __parse_connection_string_w( &con_struct,
388 conn_str_in, len_conn_str_in );
389 }
390 }
391 else {
392 char *ansi_conn_str_in;
393
394 if ( !conn_str_in )
395 {
396 ansi_conn_str_in = "";
397 len_conn_str_in = strlen( ansi_conn_str_in );
398
399 __parse_connection_string( &con_struct,
400 ansi_conn_str_in, len_conn_str_in );
401 }
402 else {
403 __parse_connection_string_w( &con_struct,
404 conn_str_in, len_conn_str_in );
405 }
406
407 if ( !__get_attribute_value( &con_struct, "DSN" ) &&
408 !__get_attribute_value( &con_struct, "DRIVER" ) &&
409 !__get_attribute_value( &con_struct, "FILEDSN" ))
410 {
411 int ret;
412 SQLCHAR returned_dsn[ 1025 ], *prefix, *target;
413
414 /*
415 * try and call GUI to obtain a DSN
416 */
417
418 ret = _SQLDriverConnectPrompt( hwnd, returned_dsn, sizeof( returned_dsn ));
419 if ( !ret || returned_dsn[ 0 ] == '\0' )
420 {
421 __append_pair( &con_struct, "DSN", "DEFAULT" );
422 }
423 else
424 {
425 prefix = returned_dsn;
426 target = (SQLCHAR*)strchr( (char*)returned_dsn, '=' );
427 if ( target )
428 {
429 *target = '\0';
430 target ++;
431 __append_pair( &con_struct, (char*)prefix, (char*)target );
432 }
433 else {
434 __append_pair( &con_struct, "DSN", (char*)returned_dsn );
435 }
436 }
437
438 /*
439 * regenerate to pass to driver
440 */
441 __generate_connection_string( &con_struct, (char*)local_conn_str_in, sizeof( local_conn_str_in ));
442 len_conn_str_in = strlen((char*) local_conn_str_in );
443 ansi_to_unicode_copy( local_conn_string, (char*)local_conn_str_in, len_conn_str_in, connection, NULL );
444 conn_str_in = local_conn_string;
445 }
446 }
447
448 /*
449 * look for some keywords
450 *
451 * TO_DO FILEDSN's
452 *
453 * have we got a DRIVER= attribute
454 */
455
456 driver = __get_attribute_value( &con_struct, "DRIVER" );
457 if ( driver )
458 {
459 /*
460 * look up the driver in the ini file
461 */
462
463 strcpy( driver_name, driver );
464
465#ifdef PLATFORM64
466 SQLGetPrivateProfileString( driver, "Driver64", "",
467 lib_name, sizeof( lib_name ), "ODBCINST.INI" );
468
469 if ( lib_name[ 0 ] == '\0' )
470 {
471 SQLGetPrivateProfileString( driver, "Driver", "",
472 lib_name, sizeof( lib_name ), "ODBCINST.INI" );
473 }
474#else
475 SQLGetPrivateProfileString( driver, "Driver", "",
476 lib_name, sizeof( lib_name ), "ODBCINST.INI" );
477#endif
478
479 /*
480 * Assume if it's not in a odbcinst.ini then it's a direct reference
481 */
482
483 if ( lib_name[ 0 ] == '\0' ) {
484 strcpy( lib_name, driver );
485 }
486
487 strcpy( connection -> dsn, "" );
488 __handle_attr_extensions( connection, NULL, driver_name );
489 }
490 else
491 {
492 dsn = __get_attribute_value( &con_struct, "DSN" );
493
494 if ( !dsn )
495 {
496 dm_log_write( __FILE__,
497 __LINE__,
498 LOG_INFO,
499 LOG_INFO,
500 "Error: IM002" );
501
502 __post_internal_error( &connection -> error,
503 ERROR_IM002, NULL,
504 connection -> environment -> requested_version );
505 __release_conn( &con_struct );
506
507 return function_return( SQL_HANDLE_DBC, connection, SQL_ERROR );
508 }
509
510 if ( strlen( dsn ) > SQL_MAX_DSN_LENGTH )
511 {
512 dm_log_write( __FILE__,
513 __LINE__,
514 LOG_INFO,
515 LOG_INFO,
516 "Error: IM012" );
517
518 __post_internal_error( &connection -> error,
519 ERROR_IM012, NULL,
520 connection -> environment -> requested_version );
521
522 return function_return( SQL_HANDLE_DBC, connection, SQL_ERROR );
523 }
524
525 /*
526 * look up the dsn in the ini file
527 */
528
529 if ( !__find_lib_name( dsn, lib_name, driver_name ))
530 {
531 dm_log_write( __FILE__,
532 __LINE__,
533 LOG_INFO,
534 LOG_INFO,
535 "Error: IM002" );
536
537 __post_internal_error( &connection -> error,
538 ERROR_IM002, NULL,
539 connection -> environment -> requested_version );
540 __release_conn( &con_struct );
541
542 return function_return( SQL_HANDLE_DBC, connection, SQL_ERROR );
543 }
544
545 strcpy( connection -> dsn, dsn );
546 __handle_attr_extensions( connection, dsn, driver_name );
547 }
548
549 if ( dsn )
550 {
551 /*
552 * do we have any Environment, Connection, or Statement attributes set in the ini ?
553 */
554
555 __handle_attr_extensions( connection, dsn, driver_name );
556 }
557 else {
558 /*
559 * the attributes may be in the connection string
560 */
561 __handle_attr_extensions_cs( connection, &con_struct );
562 }
563
564 __release_conn( &con_struct );
565
566 /*
567 * we have now got the name of a lib to load
568 */
569 if ( !__connect_part_one( connection, lib_name, driver_name, &warnings ))
570 {
571 __disconnect_part_four( connection ); /* release unicode handles */
572 return function_return( SQL_HANDLE_DBC, connection, SQL_ERROR );
573 }
574
575 if ( !CHECK_SQLDRIVERCONNECTW( connection ) &&
576 !CHECK_SQLDRIVERCONNECT( connection ))
577 {
578 dm_log_write( __FILE__,
579 __LINE__,
580 LOG_INFO,
581 LOG_INFO,
582 "Error: IM001" );
583
584 __disconnect_part_one( connection );
585 __disconnect_part_four( connection ); /* release unicode handles */
586 __post_internal_error( &connection -> error,
587 ERROR_IM001, NULL,
588 connection -> environment -> requested_version );
589
590 return function_return( SQL_HANDLE_DBC, connection, SQL_ERROR );
591 }
592
593 if ( CHECK_SQLDRIVERCONNECTW( connection ))
594 {
595 if ( CHECK_SQLSETCONNECTATTR( connection ))
596 {
597 int lret;
598
599 lret = SQLSETCONNECTATTR( connection,
600 connection -> driver_dbc,
601 SQL_ATTR_ANSI_APP,
602 SQL_AA_FALSE,
603 0 );
604 }
605
606 ret_from_connect = SQLDRIVERCONNECTW( connection,
607 connection -> driver_dbc,
608 hwnd,
609 conn_str_in,
610 len_conn_str_in,
611 conn_str_out,
612 conn_str_out_max,
613 ptr_conn_str_out,
614 driver_completion );
615
616 if ( ret_from_connect != SQL_SUCCESS )
617 {
618 SQLWCHAR sqlstate[ 6 ];
619 SQLINTEGER native_error;
620 SQLSMALLINT ind;
621 SQLWCHAR message_text[ SQL_MAX_MESSAGE_LENGTH + 1 ];
622 SQLRETURN ret;
623
624 /*
625 * get the errors from the driver before
626 * loseing the connection
627 */
628
629 if ( CHECK_SQLERRORW( connection ))
630 {
631 do
632 {
633 ret = SQLERRORW( connection,
634 SQL_NULL_HENV,
635 connection -> driver_dbc,
636 SQL_NULL_HSTMT,
637 sqlstate,
638 &native_error,
639 message_text,
640 sizeof( message_text ),
641 &ind );
642
643
644 if ( SQL_SUCCEEDED( ret ))
645 {
646 __post_internal_error_ex_w_noprefix( &connection -> error,
647 sqlstate,
648 native_error,
649 message_text,
650 SUBCLASS_ODBC, SUBCLASS_ODBC );
651 }
652 }
653 while( SQL_SUCCEEDED( ret ));
654 }
655 else if ( CHECK_SQLGETDIAGRECW( connection ))
656 {
657 int rec = 1;
658
659 do
660 {
661 ret = SQLGETDIAGRECW( connection,
662 SQL_HANDLE_DBC,
663 connection -> driver_dbc,
664 rec ++,
665 sqlstate,
666 &native_error,
667 message_text,
668 sizeof( message_text ),
669 &ind );
670
671
672 if ( SQL_SUCCEEDED( ret ))
673 {
674 __post_internal_error_ex_w_noprefix( &connection -> error,
675 sqlstate,
676 native_error,
677 message_text,
678 SUBCLASS_ODBC, SUBCLASS_ODBC );
679 }
680 }
681 while( SQL_SUCCEEDED( ret ));
682 }
683
684
685 /*
686 * if it was a error then return now
687 */
688
689 if ( !SQL_SUCCEEDED( ret_from_connect ))
690 {
691 __disconnect_part_one( connection );
692 __disconnect_part_four( connection ); /* release unicode handles */
693
694 sprintf( connection -> msg,
695 "\n\t\tExit:[%s]",
696 __get_return_status( ret_from_connect, s1 ));
697
698 dm_log_write( __FILE__,
699 __LINE__,
700 LOG_INFO,
701 LOG_INFO,
702 connection -> msg );
703
704 return function_return( SQL_HANDLE_DBC, connection, ret_from_connect );
705 }
706 }
707 connection -> unicode_driver = 1;
708 }
709 else
710 {
711 char *in_str, *out_str;
712 int len;
713
714 if ( conn_str_in )
715 {
716 if ( len_conn_str_in == SQL_NTS )
717 {
718 len = wide_strlen( conn_str_in ) + sizeof( SQLWCHAR );
719 }
720 else
721 {
722 len = len_conn_str_in + sizeof( SQLWCHAR );
723 }
724 in_str = malloc( len );
725 unicode_to_ansi_copy( in_str, len, conn_str_in, len, connection, NULL );
726 }
727 else
728 {
729 in_str = NULL;
730 }
731
732 if ( conn_str_out && conn_str_out_max > 0 )
733 {
734 out_str = malloc( conn_str_out_max + sizeof( SQLWCHAR ) );
735 }
736 else
737 {
738 out_str = NULL;
739 }
740
741 ret_from_connect = SQLDRIVERCONNECT( connection,
742 connection -> driver_dbc,
743 hwnd,
744 (SQLCHAR*)in_str,
745 len_conn_str_in,
746 (SQLCHAR*)out_str,
747 conn_str_out_max,
748 ptr_conn_str_out,
749 driver_completion );
750
751 if ( in_str )
752 {
753 free( in_str );
754 }
755
756 if ( out_str )
757 {
758 if ( SQL_SUCCEEDED( ret_from_connect ))
759 {
760 ansi_to_unicode_copy( conn_str_out, out_str, SQL_NTS, connection, NULL );
761 }
762
763 free( out_str );
764 }
765
766 if ( ret_from_connect != SQL_SUCCESS )
767 {
768 SQLCHAR sqlstate[ 6 ];
769 SQLINTEGER native_error;
770 SQLSMALLINT ind;
771 SQLCHAR message_text[ SQL_MAX_MESSAGE_LENGTH + 1 ];
772 SQLRETURN ret;
773
774 /*
775 * get the errors from the driver before
776 * loseing the connection
777 */
778
779 if ( CHECK_SQLERROR( connection ))
780 {
781 do
782 {
783 ret = SQLERROR( connection,
784 SQL_NULL_HENV,
785 connection -> driver_dbc,
786 SQL_NULL_HSTMT,
787 sqlstate,
788 &native_error,
789 message_text,
790 sizeof( message_text ),
791 &ind );
792
793 if ( SQL_SUCCEEDED( ret ))
794 {
795 __post_internal_error_ex_noprefix( &connection -> error,
796 sqlstate,
797 native_error,
798 message_text,
799 SUBCLASS_ODBC, SUBCLASS_ODBC );
800 }
801 }
802 while( SQL_SUCCEEDED( ret ));
803 }
804 else if ( CHECK_SQLGETDIAGREC( connection ))
805 {
806 int rec = 1;
807
808 do
809 {
810 ret = SQLGETDIAGREC( connection,
811 SQL_HANDLE_DBC,
812 connection -> driver_dbc,
813 rec ++,
814 sqlstate,
815 &native_error,
816 message_text,
817 sizeof( message_text ),
818 &ind );
819
820 if ( SQL_SUCCEEDED( ret ))
821 {
822 __post_internal_error_ex_noprefix( &connection -> error,
823 sqlstate,
824 native_error,
825 message_text,
826 SUBCLASS_ODBC, SUBCLASS_ODBC );
827 }
828 }
829 while( SQL_SUCCEEDED( ret ));
830 }
831
832 /*
833 * if it was a error then return now
834 */
835
836 if ( !SQL_SUCCEEDED( ret_from_connect ))
837 {
838 __disconnect_part_one( connection );
839 __disconnect_part_four( connection ); /* release unicode handles */
840
841 sprintf( connection -> msg,
842 "\n\t\tExit:[%s]",
843 __get_return_status( ret_from_connect, s1 ));
844
845 dm_log_write( __FILE__,
846 __LINE__,
847 LOG_INFO,
848 LOG_INFO,
849 connection -> msg );
850
851 return function_return( SQL_HANDLE_DBC, connection, ret_from_connect );
852 }
853 }
854 connection -> unicode_driver = 0;
855 }
856
857 /*
858 * we should be connected now
859 */
860
861 connection -> state = STATE_C4;
862
863 /*
864 * did we get the type we wanted
865 */
866
867 if ( connection -> driver_version !=
868 connection -> environment -> requested_version )
869 {
870 connection -> driver_version =
871 connection -> environment -> requested_version;
872
873 __post_internal_error( &connection -> error,
874 ERROR_01000, "Driver does not support the requested version",
875 connection -> environment -> requested_version );
876 ret_from_connect = SQL_SUCCESS_WITH_INFO;
877 }
878
879 if ( !__connect_part_two( connection ))
880 {
881 __disconnect_part_two( connection );
882 __disconnect_part_one( connection );
883 __disconnect_part_four( connection ); /* release unicode handles */
884
885 return function_return( SQL_HANDLE_DBC, connection, SQL_ERROR );
886 }
887
888 if ( log_info.log_flag )
889 {
890 if ( conn_str_out && wide_strlen( conn_str_out ) > 64 )
891 {
892 sprintf( connection -> msg,
893 "\n\t\tExit:[%s]\
894 \n\t\t\tConnection Out [%.64s...]",
895 __get_return_status( ret_from_connect, s1 ),
896 __wstring_with_length_hide_pwd( s1, conn_str_out, SQL_NTS ));
897 }
898 else
899 {
900 char null[ 20 ];
901
902 strcpy( null, "NULL" );
903
904 sprintf( connection -> msg,
905 "\n\t\tExit:[%s]\
906 \n\t\t\tConnection Out [%s]",
907 __get_return_status( ret_from_connect, s1 ),
908 __wstring_with_length_hide_pwd( s1, conn_str_out, SQL_NTS ));
909 }
910
911 dm_log_write( __FILE__,
912 __LINE__,
913 LOG_INFO,
914 LOG_INFO,
915 connection -> msg );
916 }
917
918 if ( warnings && ret_from_connect == SQL_SUCCESS )
919 {
920 ret_from_connect = SQL_SUCCESS_WITH_INFO;
921 }
922
923 return function_return_nodrv( SQL_HANDLE_DBC, connection, ret_from_connect );
924}
925