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: SQLSetConnectAttrW.c,v 1.14 2009/02/18 17:59:08 lurcher Exp $
31  *
32  * $Log: SQLSetConnectAttrW.c,v $
33  * Revision 1.14  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.13  2008/08/29 08:01:39  lurcher
37  * Alter the way W functions are passed to the driver
38  *
39  * Revision 1.12  2007/02/28 15:37:48  lurcher
40  * deal with drivers that call internal W functions and end up in the driver manager. controlled by the --enable-handlemap configure arg
41  *
42  * Revision 1.11  2006/04/18 10:24:47  lurcher
43  * Add a couple of changes from Mark Vanderwiel
44  *
45  * Revision 1.10  2003/10/30 18:20:46  lurcher
46  *
47  * Fix broken thread protection
48  * Remove SQLNumResultCols after execute, lease S4/S% to driver
49  * Fix string overrun in SQLDriverConnect
50  * Add initial support for Interix
51  *
52  * Revision 1.9  2003/03/05 09:48:44  lurcher
53  *
54  * Add some 64 bit fixes
55  *
56  * Revision 1.8  2002/12/05 17:44:31  lurcher
57  *
58  * Display unknown return values in return logging
59  *
60  * Revision 1.7  2002/08/23 09:42:37  lurcher
61  *
62  * Fix some build warnings with casts, and a AIX linker mod, to include
63  * deplib's on the link line, but not the libtool generated ones
64  *
65  * Revision 1.6  2002/07/24 08:49:52  lurcher
66  *
67  * Alter UNICODE support to use iconv for UNICODE-ANSI conversion
68  *
69  * Revision 1.5  2002/07/16 13:08:18  lurcher
70  *
71  * Filter attribute values from SQLSetStmtAttr to SQLSetStmtOption to fit
72  * within ODBC 2
73  * Make DSN's double clickable in ODBCConfig
74  *
75  * Revision 1.4  2002/07/04 17:27:56  lurcher
76  *
77  * Small bug fixes
78  *
79  * Revision 1.3  2002/01/30 12:20:02  lurcher
80  *
81  * Add MyODBC 3 driver source
82  *
83  * Revision 1.2  2001/12/13 13:00:32  lurcher
84  *
85  * Remove most if not all warnings on 64 bit platforms
86  * Add support for new MS 3.52 64 bit changes
87  * Add override to disable the stopping of tracing
88  * Add MAX_ROWS support in postgres driver
89  *
90  * Revision 1.1.1.1  2001/10/17 16:40:07  lurcher
91  *
92  * First upload to SourceForge
93  *
94  * Revision 1.7  2001/09/27 17:05:48  nick
95  *
96  * Assorted fixes and tweeks
97  *
98  * Revision 1.6  2001/08/08 17:05:17  nick
99  *
100  * Add support for attribute setting in the ini files
101  *
102  * Revision 1.5  2001/08/03 15:19:00  nick
103  *
104  * Add changes to set values before connect
105  *
106  * Revision 1.4  2001/07/03 09:30:41  nick
107  *
108  * Add ability to alter size of displayed message in the log
109  *
110  * Revision 1.3  2001/05/23 13:48:37  nick
111  *
112  * Remove unwanted include
113  *
114  * Revision 1.2  2001/04/12 17:43:36  nick
115  *
116  * Change logging and added autotest to odbctest
117  *
118  * Revision 1.1  2000/12/31 20:30:54  nick
119  *
120  * Add UNICODE support
121  *
122  *
123  **********************************************************************/
124 
125 #include <config.h>
126 #include "drivermanager.h"
127 
128 static char const rcsid[]= "$RCSfile: SQLSetConnectAttrW.c,v $";
129 
SQLSetConnectAttrW(SQLHDBC connection_handle,SQLINTEGER attribute,SQLPOINTER value,SQLINTEGER string_length)130 SQLRETURN SQLSetConnectAttrW( SQLHDBC connection_handle,
131            SQLINTEGER attribute,
132            SQLPOINTER value,
133            SQLINTEGER string_length )
134 {
135     DMHDBC connection = (DMHDBC)connection_handle;
136     SQLRETURN ret;
137     SQLCHAR s1[ 100 + LOG_MESSAGE_LEN ];
138 	SQLWCHAR buffer[ 512 ];
139 
140     /*
141      * doesn't require a handle
142      */
143 
144     if ( attribute == SQL_ATTR_TRACE )
145     {
146         if ((SQLLEN) value != SQL_OPT_TRACE_OFF &&
147             (SQLLEN) value != SQL_OPT_TRACE_ON )
148         {
149             if ( __validate_dbc( connection ))
150             {
151                 thread_protect( SQL_HANDLE_DBC, connection );
152                 dm_log_write( __FILE__,
153                         __LINE__,
154                         LOG_INFO,
155                         LOG_INFO,
156                         "Error: HY024" );
157 
158                 function_entry( connection );
159                 __post_internal_error( &connection -> error,
160                     ERROR_HY024, NULL,
161                     connection -> environment -> requested_version );
162 
163                 return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
164             }
165             else
166             {
167                 return SQL_INVALID_HANDLE;
168             }
169         }
170 
171         if ((SQLLEN) value == SQL_OPT_TRACE_OFF )
172         {
173             char force_string[ 30 ];
174 
175             SQLGetPrivateProfileString( "ODBC", "ForceTrace", "0",
176 				force_string, sizeof( force_string ),
177                 "ODBCINST.INI" );
178 
179             if ( force_string[ 0 ] == '1' ||
180                 toupper( force_string[ 0 ] ) == 'Y' ||
181                 ( toupper( force_string[ 0 ] ) == 'O' &&
182                     toupper( force_string[ 1 ] ) == 'N' ))
183             {
184                 if ( log_info.log_flag )
185                 {
186                     dm_log_write( __FILE__,
187                         __LINE__,
188                         LOG_INFO,
189                         LOG_INFO,
190                         "Application tried to turn logging off" );
191                 }
192             }
193             else
194             {
195                 if ( log_info.log_flag )
196                 {
197                     dm_log_write( __FILE__,
198                         __LINE__,
199                         LOG_INFO,
200                         LOG_INFO,
201                         "Application turning logging off" );
202                 }
203                 log_info.log_flag = 0;
204             }
205         }
206         else
207         {
208             log_info.log_flag = 1;
209         }
210 
211         return SQL_SUCCESS;
212     }
213     else if ( attribute == SQL_ATTR_TRACEFILE )
214     {
215         if ( value )
216         {
217             if (((SQLWCHAR*)value)[ 0 ] == 0 )
218             {
219                 if ( __validate_dbc( connection ))
220                 {
221                     thread_protect( SQL_HANDLE_DBC, connection );
222                     dm_log_write( __FILE__,
223                             __LINE__,
224                             LOG_INFO,
225                             LOG_INFO,
226                             "Error: HY024" );
227 
228                     function_entry( connection );
229                     __post_internal_error( &connection -> error,
230                         ERROR_HY024, NULL,
231                         connection -> environment -> requested_version );
232 
233                     return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
234                 }
235                 else
236                 {
237                     return SQL_INVALID_HANDLE;
238                 }
239             }
240             else
241             {
242                 if ( log_info.log_file_name )
243                 {
244                     free( log_info.log_file_name );
245                 }
246                 log_info.log_file_name = unicode_to_ansi_alloc((SQLWCHAR *) value, SQL_NTS, connection, NULL );
247             }
248         }
249         else
250         {
251             if ( __validate_dbc( connection ))
252             {
253                 thread_protect( SQL_HANDLE_DBC, connection );
254                 dm_log_write( __FILE__,
255                         __LINE__,
256                         LOG_INFO,
257                         LOG_INFO,
258                         "Error: HY024" );
259 
260                 function_entry( connection );
261                 __post_internal_error( &connection -> error,
262                     ERROR_HY024, NULL,
263                     connection -> environment -> requested_version );
264 
265                 return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
266             }
267             else
268             {
269                 return SQL_INVALID_HANDLE;
270             }
271         }
272         return SQL_SUCCESS;
273     }
274 
275     /*
276      * check connection
277      */
278 
279     if ( !__validate_dbc( connection ))
280     {
281         dm_log_write( __FILE__,
282                     __LINE__,
283                     LOG_INFO,
284                     LOG_INFO,
285                     "Error: SQL_INVALID_HANDLE" );
286 
287 #ifdef WITH_HANDLE_REDIRECT
288 		{
289 			DMHDBC parent_connection;
290 
291 			parent_connection = find_parent_handle( connection, SQL_HANDLE_DBC );
292 
293 			if ( parent_connection ) {
294         		dm_log_write( __FILE__,
295                 	__LINE__,
296                     	LOG_INFO,
297                     	LOG_INFO,
298                     	"Info: found parent handle" );
299 
300 				if ( CHECK_SQLSETCONNECTATTRW( parent_connection ))
301 				{
302         			dm_log_write( __FILE__,
303                 		__LINE__,
304                    		 	LOG_INFO,
305                    		 	LOG_INFO,
306                    		 	"Info: calling redirected driver function" );
307 
308 					return SQLSETCONNECTATTRW( parent_connection,
309 							connection_handle,
310            					attribute,
311            					value,
312            					string_length );
313 				}
314 			}
315 		}
316 #endif
317         return SQL_INVALID_HANDLE;
318     }
319 
320     function_entry( connection );
321 
322     if ( log_info.log_flag )
323     {
324         sprintf( connection -> msg, "\n\t\tEntry:\
325 \n\t\t\tConnection = %p\
326 \n\t\t\tAttribute = %s\
327 \n\t\t\tValue = %p\
328 \n\t\t\tStrLen = %d",
329                 connection,
330                 __con_attr_as_string( s1, attribute ),
331                 value,
332                 (int)string_length );
333 
334         dm_log_write( __FILE__,
335                 __LINE__,
336                 LOG_INFO,
337                 LOG_INFO,
338                 connection -> msg );
339     }
340 
341     thread_protect( SQL_HANDLE_DBC, connection );
342 
343     if ( connection -> state == STATE_C2 )
344     {
345         if ( attribute == SQL_ATTR_TRANSLATE_OPTION ||
346                 attribute == SQL_ATTR_TRANSLATE_LIB )
347         {
348             dm_log_write( __FILE__,
349                     __LINE__,
350                     LOG_INFO,
351                     LOG_INFO,
352                     "Error: 08003" );
353 
354             __post_internal_error( &connection -> error,
355                 ERROR_08003, NULL,
356                 connection -> environment -> requested_version );
357 
358             return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
359         }
360     }
361     else if ( connection -> state == STATE_C3 )
362     {
363         dm_log_write( __FILE__,
364                 __LINE__,
365                 LOG_INFO,
366                 LOG_INFO,
367                 "Error: HY010" );
368 
369         __post_internal_error( &connection -> error,
370             ERROR_HY010, NULL,
371             connection -> environment -> requested_version );
372 
373         return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
374     }
375     else if ( connection -> state == STATE_C4 ||
376             connection -> state == STATE_C5 ||
377             connection -> state == STATE_C6 )
378     {
379         if ( attribute == SQL_ATTR_ODBC_CURSORS )
380         {
381             dm_log_write( __FILE__,
382                     __LINE__,
383                     LOG_INFO,
384                     LOG_INFO,
385                     "Error: 08002" );
386 
387             __post_internal_error( &connection -> error,
388                 ERROR_08002, NULL,
389                 connection -> environment -> requested_version );
390 
391             return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
392         }
393         else if ( attribute == SQL_ATTR_PACKET_SIZE )
394         {
395             dm_log_write( __FILE__,
396                     __LINE__,
397                     LOG_INFO,
398                     LOG_INFO,
399                     "Error: HY011" );
400 
401             __post_internal_error( &connection -> error,
402                 ERROR_HY011, NULL,
403                 connection -> environment -> requested_version );
404 
405             return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
406         }
407     }
408 
409     /*
410      * is it a legitimate value
411      */
412     ret = dm_check_connection_attrs( connection, attribute, value );
413 
414     if ( ret != SQL_SUCCESS )
415     {
416         dm_log_write( __FILE__,
417                     __LINE__,
418                     LOG_INFO,
419                     LOG_INFO,
420                     "Error: HY024" );
421 
422         __post_internal_error( &connection -> error,
423                 ERROR_HY024, NULL,
424                 connection -> environment -> requested_version );
425 
426         return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
427     }
428 
429     /*
430      * is it a connection attribute or statement, check state of any active connections
431      */
432 
433     switch( attribute )
434     {
435         /* ODBC 3.x statement attributes are not settable at the connection level */
436         case SQL_ATTR_APP_PARAM_DESC:
437         case SQL_ATTR_APP_ROW_DESC:
438         case SQL_ATTR_CURSOR_SCROLLABLE:
439         case SQL_ATTR_CURSOR_SENSITIVITY:
440         case SQL_ATTR_ENABLE_AUTO_IPD:
441         case SQL_ATTR_FETCH_BOOKMARK_PTR:
442         case SQL_ATTR_IMP_PARAM_DESC:
443         case SQL_ATTR_IMP_ROW_DESC:
444         case SQL_ATTR_PARAM_BIND_OFFSET_PTR:
445         case SQL_ATTR_PARAM_BIND_TYPE:
446         case SQL_ATTR_PARAM_OPERATION_PTR:
447         case SQL_ATTR_PARAM_STATUS_PTR:
448         case SQL_ATTR_PARAMS_PROCESSED_PTR:
449         case SQL_ATTR_PARAMSET_SIZE:
450         case SQL_ATTR_ROW_ARRAY_SIZE:
451         case SQL_ATTR_ROW_BIND_OFFSET_PTR:
452         case SQL_ATTR_ROW_OPERATION_PTR:
453         case SQL_ATTR_ROW_STATUS_PTR:
454         case SQL_ATTR_ROWS_FETCHED_PTR:
455             __post_internal_error( &connection -> error,
456                     ERROR_HY092, NULL,
457                     connection -> environment -> requested_version );
458 
459             return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
460 
461       	case SQL_ATTR_CONCURRENCY:
462 	  	case SQL_BIND_TYPE:
463       	case SQL_ATTR_CURSOR_TYPE:
464       	case SQL_ATTR_MAX_LENGTH:
465       	case SQL_MAX_ROWS:
466       	case SQL_ATTR_KEYSET_SIZE:
467       	case SQL_ROWSET_SIZE:
468       	case SQL_ATTR_NOSCAN:
469       	case SQL_ATTR_QUERY_TIMEOUT:
470       	case SQL_ATTR_RETRIEVE_DATA:
471       	case SQL_ATTR_SIMULATE_CURSOR:
472       	case SQL_ATTR_USE_BOOKMARKS:
473             if( __check_stmt_from_dbc_v( connection, 8, STATE_S8, STATE_S9, STATE_S10, STATE_S11, STATE_S12, STATE_S13, STATE_S14, STATE_S15 )) {
474 
475                 dm_log_write( __FILE__,
476                         __LINE__,
477                         LOG_INFO,
478                         LOG_INFO,
479                         "Error: 24000" );
480 
481                 __post_internal_error( &connection -> error,
482                         ERROR_24000, NULL,
483                         connection -> environment -> requested_version );
484 
485                 return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
486             }
487             break;
488 
489         default:
490 
491             if( __check_stmt_from_dbc_v( connection, 8, STATE_S8, STATE_S9, STATE_S10, STATE_S11, STATE_S12, STATE_S13, STATE_S14, STATE_S15 )) {
492 
493                 dm_log_write( __FILE__,
494                         __LINE__,
495                         LOG_INFO,
496                         LOG_INFO,
497                         "Error: HY010" );
498 
499                 __post_internal_error( &connection -> error,
500                         ERROR_HY010, NULL,
501                         connection -> environment -> requested_version );
502 
503                 return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
504             }
505             break;
506     }
507 
508     /*
509      * is it something overridden
510      */
511 
512     value = __attr_override_wide( connection, SQL_HANDLE_DBC, attribute, value, &string_length, buffer );
513 
514     /*
515      * we need to save this even if connected so we can use it for the next connect
516      */
517     if ( attribute == SQL_ATTR_LOGIN_TIMEOUT )
518     {
519         connection -> login_timeout = ( SQLLEN ) value;
520         connection -> login_timeout_set = 1;
521     }
522 
523     /*
524      * if connected, call the driver
525      * otherwise we need to save the states and set them when we
526      * do connect
527      */
528     if ( connection -> state == STATE_C2 )
529     {
530         /*
531          * is it for us
532          */
533 
534         if ( attribute == SQL_ATTR_ODBC_CURSORS )
535         {
536             connection -> cursors = ( SQLLEN ) value;
537         }
538         else if ( attribute == SQL_ATTR_ACCESS_MODE )
539         {
540             connection -> access_mode = ( SQLLEN ) value;
541             connection -> access_mode_set = 1;
542         }
543         else if ( attribute == SQL_ATTR_ASYNC_ENABLE )
544         {
545             connection -> async_enable = ( SQLLEN ) value;
546             connection -> async_enable_set = 1;
547         }
548         else if ( attribute == SQL_ATTR_AUTO_IPD )
549         {
550             connection -> auto_ipd = ( SQLLEN ) value;
551             connection -> auto_ipd_set = 1;
552         }
553         else if ( attribute == SQL_ATTR_AUTOCOMMIT )
554         {
555             connection -> auto_commit = ( SQLLEN ) value;
556             connection -> auto_commit_set = 1;
557         }
558         else if ( attribute == SQL_ATTR_CONNECTION_TIMEOUT )
559         {
560             connection -> connection_timeout = ( SQLLEN ) value;
561             connection -> connection_timeout_set = 1;
562         }
563         else if ( attribute == SQL_ATTR_METADATA_ID )
564         {
565             connection -> metadata_id = ( SQLLEN ) value;
566             connection -> metadata_id_set = 1;
567         }
568         else if ( attribute == SQL_ATTR_PACKET_SIZE )
569         {
570             connection -> packet_size = ( SQLLEN ) value;
571             connection -> packet_size_set = 1;
572         }
573         else if ( attribute == SQL_ATTR_QUIET_MODE )
574         {
575             connection -> quite_mode = ( SQLLEN ) value;
576             connection -> quite_mode_set = 1;
577         }
578         else if ( attribute == SQL_ATTR_TXN_ISOLATION )
579         {
580             connection -> txn_isolation = ( SQLLEN ) value;
581             connection -> txn_isolation_set = 1;
582         }
583         else if ( attribute != SQL_ATTR_LOGIN_TIMEOUT )
584         {
585             /*
586              * save any unknown attributes untill connect
587              */
588 
589             struct save_attr *sa = calloc( 1, sizeof( struct save_attr ));
590 
591             sa -> attr_type = attribute;
592             if ( string_length > 0 )
593             {
594                 sa -> str_attr = malloc( string_length );
595                 memcpy( sa -> str_attr, value, string_length );
596                 sa -> str_len = string_length;
597             }
598             else if ( string_length == SQL_NTS )
599             {
600                 if (!value)
601                 {
602                     __post_internal_error( &connection -> error,
603                         ERROR_HY024, "Invalid argument value",
604                         connection -> environment -> requested_version );
605                     return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
606                 }
607                 else
608                 {
609                     sa -> str_attr = unicode_to_ansi_alloc( value, string_length, connection, NULL );
610                     sa -> str_len = string_length;
611                 }
612             }
613             else
614             {
615                 sa -> intptr_attr = (intptr_t) value;
616                 sa -> str_len = string_length;
617             }
618             sa -> next = connection -> save_attr;
619             connection -> save_attr = sa;
620         }
621 
622         sprintf( connection -> msg,
623                 "\n\t\tExit:[%s]",
624                     __get_return_status( SQL_SUCCESS, s1 ));
625 
626         dm_log_write( __FILE__,
627                 __LINE__,
628                 LOG_INFO,
629                 LOG_INFO,
630                 connection -> msg );
631 
632         return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_SUCCESS );
633     }
634     else
635     {
636         if ( connection -> unicode_driver ||
637 			CHECK_SQLSETCONNECTATTRW( connection ))
638         {
639             if ( !CHECK_SQLSETCONNECTATTRW( connection ))
640             {
641                 if ( CHECK_SQLSETCONNECTOPTIONW( connection ))
642                 {
643                     /*
644                      * Is it in the legal range of values
645                      */
646 
647                     if ( attribute < SQL_CONN_DRIVER_MIN &&
648                             ( attribute > SQL_PACKET_SIZE || attribute < SQL_ACCESS_MODE ))
649                     {
650                         dm_log_write( __FILE__,
651                                 __LINE__,
652                                 LOG_INFO,
653                                 LOG_INFO,
654                                 "Error: HY092" );
655 
656                         __post_internal_error( &connection -> error,
657                                 ERROR_HY092, NULL,
658                                 connection -> environment -> requested_version );
659 
660                         return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
661                     }
662 
663                     ret = SQLSETCONNECTOPTIONW( connection,
664                             connection -> driver_dbc,
665                             attribute,
666                             value );
667                 }
668                 else
669                 {
670                     dm_log_write( __FILE__,
671                             __LINE__,
672                             LOG_INFO,
673                             LOG_INFO,
674                             "Error: IM001" );
675 
676                     __post_internal_error( &connection -> error,
677                             ERROR_IM001, NULL,
678                             connection -> environment -> requested_version );
679 
680                     return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
681                 }
682             }
683             else
684             {
685                 ret = SQLSETCONNECTATTRW( connection,
686                         connection -> driver_dbc,
687                         attribute,
688                         value,
689                         string_length );
690             }
691         }
692         else
693         {
694             if ( !CHECK_SQLSETCONNECTATTR( connection ))
695             {
696                 if ( CHECK_SQLSETCONNECTOPTION( connection ))
697                 {
698                     SQLCHAR *as1 = NULL;
699 
700                     /*
701                      * Is it in the legal range of values
702                      */
703 
704                     if ( attribute < SQL_CONN_DRIVER_MIN &&
705                             ( attribute > SQL_PACKET_SIZE || attribute < SQL_ACCESS_MODE ))
706                     {
707                         dm_log_write( __FILE__,
708                                 __LINE__,
709                                 LOG_INFO,
710                                 LOG_INFO,
711                                 "Error: HY092" );
712 
713                         __post_internal_error( &connection -> error,
714                                 ERROR_HY092, NULL,
715                                 connection -> environment -> requested_version );
716 
717                         return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
718                     }
719 
720                     switch( attribute )
721                     {
722                       case SQL_ATTR_CURRENT_CATALOG:
723                       case SQL_ATTR_TRACEFILE:
724                       case SQL_ATTR_TRANSLATE_LIB:
725                         if ( value )
726                         {
727                             as1 = (SQLCHAR*) unicode_to_ansi_alloc( value, SQL_NTS, connection, NULL );
728                         }
729                         break;
730                     }
731 
732                     ret = SQLSETCONNECTOPTION( connection,
733                             connection -> driver_dbc,
734                             attribute,
735                             as1 ? as1 : value );
736 
737                     if ( as1 ) free( as1 );
738                 }
739                 else
740                 {
741                     dm_log_write( __FILE__,
742                             __LINE__,
743                             LOG_INFO,
744                             LOG_INFO,
745                             "Error: IM001" );
746 
747                     __post_internal_error( &connection -> error,
748                             ERROR_IM001, NULL,
749                             connection -> environment -> requested_version );
750 
751                     return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
752                 }
753             }
754             else
755             {
756                 SQLCHAR *as1 = NULL;
757 
758                 switch( attribute )
759                 {
760                   case SQL_ATTR_CURRENT_CATALOG:
761                   case SQL_ATTR_TRACEFILE:
762                   case SQL_ATTR_TRANSLATE_LIB:
763                     if ( value )
764                     {
765                         if ( string_length > 0 )
766                         {
767                             as1 = (SQLCHAR*) unicode_to_ansi_alloc( value, string_length, connection, NULL );
768                         }
769                         else if ( string_length == SQL_NTS )
770                         {
771                             as1 = (SQLCHAR*) unicode_to_ansi_alloc( value, SQL_NTS, connection, NULL );
772                         }
773                     }
774 
775                     ret = SQLSETCONNECTATTR( connection,
776                             connection -> driver_dbc,
777                             attribute,
778                             as1 ? as1 : value,
779                             string_length / sizeof( SQLWCHAR ));
780 
781                     if ( as1 )
782                     {
783                         free( as1 );
784                     }
785                     break;
786 
787                   default:
788                     ret = SQLSETCONNECTATTR( connection,
789                             connection -> driver_dbc,
790                             attribute,
791                             value,
792                             string_length );
793                     break;
794                 }
795             }
796         }
797 
798         if ( log_info.log_flag )
799         {
800             sprintf( connection -> msg,
801                     "\n\t\tExit:[%s]",
802                         __get_return_status( ret, s1 ));
803 
804             dm_log_write( __FILE__,
805                     __LINE__,
806                     LOG_INFO,
807                     LOG_INFO,
808                     connection -> msg );
809         }
810     }
811 
812     /*
813      * catch this
814      */
815 
816     if ( attribute == SQL_ATTR_USE_BOOKMARKS && SQL_SUCCEEDED( ret ))
817     {
818         connection -> bookmarks_on = (SQLULEN) value;
819     }
820 
821     return function_return( SQL_HANDLE_DBC, connection, ret, DEFER_R3 );
822 }
823