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 | |
130 | static char const rcsid[]= "$RCSfile: SQLDriverConnectW.c,v $" ; |
131 | |
132 | int __parse_connection_string_w( struct con_struct *con_str, |
133 | SQLWCHAR *str, int str_len ) |
134 | { |
135 | struct con_pair *cp; |
136 | char *local_str, *ptr; |
137 | int len; |
138 | int got_dsn = 0; /* if we have a DSN then ignore any DRIVER or FILEDSN */ |
139 | int 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 | |
196 | SQLRETURN 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 | |