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: SQLGetConnectOptionW.c,v 1.10 2009/02/18 17:59:08 lurcher Exp $
31  *
32  * $Log: SQLGetConnectOptionW.c,v $
33  * Revision 1.10  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.9  2009/02/17 09:47:44  lurcher
37  * Clear up a number of bugs
38  *
39  * Revision 1.8  2008/08/29 08:01:38  lurcher
40  * Alter the way W functions are passed to the driver
41  *
42  * Revision 1.7  2007/02/28 15:37:48  lurcher
43  * deal with drivers that call internal W functions and end up in the driver manager. controlled by the --enable-handlemap configure arg
44  *
45  * Revision 1.6  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.5  2002/12/05 17:44:30  lurcher
53  *
54  * Display unknown return values in return logging
55  *
56  * Revision 1.4  2002/11/11 17:10:12  lurcher
57  *
58  * VMS changes
59  *
60  * Revision 1.3  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.2  2002/07/24 08:49:52  lurcher
66  *
67  * Alter UNICODE support to use iconv for UNICODE-ANSI conversion
68  *
69  * Revision 1.1.1.1  2001/10/17 16:40:05  lurcher
70  *
71  * First upload to SourceForge
72  *
73  * Revision 1.4  2001/08/03 15:19:00  nick
74  *
75  * Add changes to set values before connect
76  *
77  * Revision 1.3  2001/07/03 09:30:41  nick
78  *
79  * Add ability to alter size of displayed message in the log
80  *
81  * Revision 1.2  2001/04/12 17:43:36  nick
82  *
83  * Change logging and added autotest to odbctest
84  *
85  * Revision 1.1  2000/12/31 20:30:54  nick
86  *
87  * Add UNICODE support
88  *
89  *
90  **********************************************************************/
91 
92 #include <config.h>
93 #include "drivermanager.h"
94 
95 static char const rcsid[]= "$RCSfile: SQLGetConnectOptionW.c,v $";
96 
SQLGetConnectOptionW(SQLHDBC connection_handle,SQLUSMALLINT option,SQLPOINTER value)97 SQLRETURN SQLGetConnectOptionW( SQLHDBC connection_handle,
98            SQLUSMALLINT option,
99            SQLPOINTER value )
100 {
101     DMHDBC connection = (DMHDBC)connection_handle;
102     int type = 0;
103     SQLCHAR s1[ 100 + LOG_MESSAGE_LEN ];
104 
105     /*
106      * doesn't require a handle
107      */
108 
109     if ( option == SQL_ATTR_TRACE )
110     {
111         if ( value )
112         {
113             *((SQLINTEGER*)value) = SQL_OPT_TRACE_ON;
114         }
115 
116         return SQL_SUCCESS;
117     }
118     else if ( option == SQL_ATTR_TRACEFILE )
119     {
120         SQLRETURN ret =  SQL_SUCCESS;
121 
122         if ( log_info.log_file_name )
123         {
124             ansi_to_unicode_copy( value, log_info.log_file_name, SQL_NTS, connection, NULL );
125         }
126         else
127         {
128             ansi_to_unicode_copy( value, "", SQL_NTS, connection, NULL );
129         }
130         return ret;
131     }
132 
133 
134     /*
135      * check connection
136      */
137 
138     if ( !__validate_dbc( connection ))
139     {
140         dm_log_write( __FILE__,
141                     __LINE__,
142                     LOG_INFO,
143                     LOG_INFO,
144                     "Error: SQL_INVALID_HANDLE" );
145 
146 #ifdef WITH_HANDLE_REDIRECT
147 		{
148 			DMHDBC parent_connection;
149 
150 			parent_connection = find_parent_handle( connection, SQL_HANDLE_DBC );
151 
152 			if ( parent_connection ) {
153         		dm_log_write( __FILE__,
154                 	__LINE__,
155                     	LOG_INFO,
156                     	LOG_INFO,
157                     	"Info: found parent handle" );
158 
159 				if ( CHECK_SQLGETCONNECTOPTIONW( parent_connection ))
160 				{
161         			dm_log_write( __FILE__,
162                 		__LINE__,
163                    		 	LOG_INFO,
164                    		 	LOG_INFO,
165                    		 	"Info: calling redirected driver function" );
166 
167 					return SQLGETCONNECTOPTIONW( parent_connection,
168 							connection,
169 							option,
170 							value );
171 				}
172 			}
173 		}
174 #endif
175         return SQL_INVALID_HANDLE;
176     }
177 
178     function_entry( connection );
179 
180     if ( log_info.log_flag )
181     {
182         sprintf( connection -> msg, "\n\t\tEntry:\
183 \n\t\t\tConnection = %p\
184 \n\t\t\tOption = %s\
185 \n\t\t\tValue = %p",
186                 connection,
187                 __con_attr_as_string( s1, option ),
188                 value );
189 
190         dm_log_write( __FILE__,
191                 __LINE__,
192                 LOG_INFO,
193                 LOG_INFO,
194                 connection -> msg );
195     }
196 
197     thread_protect( SQL_HANDLE_DBC, connection );
198 
199     if ( connection -> state == STATE_C3 )
200     {
201         dm_log_write( __FILE__,
202                 __LINE__,
203                 LOG_INFO,
204                 LOG_INFO,
205                 "Error: HY010" );
206 
207         __post_internal_error( &connection -> error,
208                 ERROR_HY010, NULL,
209                 connection -> environment -> requested_version );
210 
211         return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
212     }
213 
214     if ( connection -> state == STATE_C2 )
215     {
216         switch ( option )
217         {
218           case SQL_ACCESS_MODE:
219           case SQL_AUTOCOMMIT:
220           case SQL_LOGIN_TIMEOUT:
221           case SQL_ODBC_CURSORS:
222             break;
223 
224           default:
225             dm_log_write( __FILE__,
226                     __LINE__,
227                     LOG_INFO,
228                     LOG_INFO,
229                     "Error: 08003" );
230 
231             __post_internal_error( &connection -> error,
232                     ERROR_08003, NULL,
233                     connection -> environment -> requested_version );
234 
235             return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
236         }
237     }
238 
239     switch ( option )
240     {
241       case SQL_ACCESS_MODE:
242         /*
243          * if connected, call the driver
244          */
245         if ( connection -> state != STATE_C2 )
246         {
247             type = 0;
248         }
249         else
250         {
251             *((SQLINTEGER*)value) = connection -> access_mode;
252             type = 1;
253         }
254         break;
255 
256       case SQL_AUTOCOMMIT:
257         /*
258          * if connected, call the driver
259          */
260         if ( connection -> state != STATE_C2 )
261         {
262             type = 0;
263         }
264         else
265         {
266             *((SQLINTEGER*)value) = connection -> auto_commit;
267             type = 1;
268         }
269         break;
270 
271       case SQL_ODBC_CURSORS:
272         *((SQLINTEGER*)value) = connection -> cursors;
273         type = 1;
274         break;
275 
276       case SQL_ATTR_LOGIN_TIMEOUT:
277         /*
278          * if connected, call the driver
279          */
280         if ( connection -> state != STATE_C2 )
281         {
282             type = 0;
283         }
284         else
285         {
286             *((SQLINTEGER*)value) = connection -> login_timeout;
287             type = 1;
288         }
289         break;
290 
291 
292       default:
293         break;
294     }
295 
296     /*
297      * if type has been set we have already set the value,
298      * so just return
299      */
300     if ( type )
301     {
302         sprintf( connection -> msg,
303                 "\n\t\tExit:[%s]",
304                     __get_return_status( SQL_SUCCESS, s1 ));
305 
306         dm_log_write( __FILE__,
307                 __LINE__,
308                 LOG_INFO,
309                 LOG_INFO,
310                 connection -> msg );
311 
312         return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_SUCCESS );
313     }
314     else
315     {
316         SQLRETURN ret = 0;
317 
318         /*
319          * call the driver
320          */
321         if ( connection -> unicode_driver ||
322 			CHECK_SQLGETCONNECTOPTIONW( connection ) ||
323 			CHECK_SQLGETCONNECTATTRW( connection ))
324         {
325             if ( CHECK_SQLGETCONNECTOPTIONW( connection ))
326             {
327                 ret = SQLGETCONNECTOPTIONW( connection,
328                         connection -> driver_dbc,
329                         option,
330                         value );
331             }
332             else if ( CHECK_SQLGETCONNECTATTRW( connection ))
333             {
334                 SQLINTEGER length, len;
335                 void * ptr;
336                 SQLWCHAR txt[ 1024 ];
337 
338                 switch( option )
339                 {
340                   case SQL_ATTR_CURRENT_CATALOG:
341                   case SQL_ATTR_TRACEFILE:
342                   case SQL_ATTR_TRANSLATE_LIB:
343                     length = sizeof( txt );
344                     ptr = txt;
345                     break;
346 
347                   default:
348                     length = sizeof( SQLINTEGER );
349                     ptr = value;
350                     break;
351 
352                 }
353 
354                 ret = SQLGETCONNECTATTRW( connection,
355                         connection -> driver_dbc,
356                         option,
357                         ptr,
358                         length,
359                         &len );
360 
361                 /*
362                  * not much else we can do here, lets assume that
363                  * there is enough space
364                  */
365 
366                 if ( ptr != value )
367                 {
368                     wide_strcpy( value, ptr );
369 
370                     /*
371                      * are we still here ? good
372                      */
373                 }
374             }
375             else
376             {
377                 __post_internal_error( &connection -> error,
378                         ERROR_IM001, NULL,
379                         connection -> environment -> requested_version );
380 
381                 return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
382             }
383         }
384         else
385         {
386             if (( ret = CHECK_SQLGETCONNECTOPTION( connection )))
387             {
388                 SQLCHAR *as1 = NULL;
389 
390                 switch( option )
391                 {
392                   case SQL_ATTR_CURRENT_CATALOG:
393                   case SQL_ATTR_TRACEFILE:
394                   case SQL_ATTR_TRANSLATE_LIB:
395                     if ( SQL_SUCCEEDED( ret ) && value )
396                     {
397                         /*
398                          * we need to chance out arm here, as we dont know
399                          */
400 
401                         as1 = malloc( 1024 );
402                     }
403                     break;
404                 }
405 
406                 ret = SQLGETCONNECTOPTION( connection,
407                         connection -> driver_dbc,
408                         option,
409                         as1 ? as1 : value );
410 
411                 switch( option )
412                 {
413                   case SQL_ATTR_CURRENT_CATALOG:
414                   case SQL_ATTR_TRACEFILE:
415                   case SQL_ATTR_TRANSLATE_LIB:
416                     if ( SQL_SUCCEEDED( ret ) && value && as1 )
417                     {
418                         ansi_to_unicode_copy( value, (char*) as1, SQL_NTS, connection, NULL );
419                     }
420 
421                     if ( as1 )
422                     {
423                         free( as1 );
424                     }
425                     break;
426                 }
427             }
428             else if ( CHECK_SQLGETCONNECTATTR( connection ))
429             {
430                 SQLINTEGER length, len;
431                 void * ptr;
432                 char txt[ 1024 ];
433 
434                 switch( option )
435                 {
436                   case SQL_ATTR_CURRENT_CATALOG:
437                   case SQL_ATTR_TRACEFILE:
438                   case SQL_ATTR_TRANSLATE_LIB:
439                     length = sizeof( txt );
440                     ptr = txt;
441                     break;
442 
443                   default:
444                     length = sizeof( SQLINTEGER );
445                     ptr = value;
446                     break;
447 
448                 }
449 
450                 ret = SQLGETCONNECTATTR( connection,
451                         connection -> driver_dbc,
452                         option,
453                         ptr,
454                         length,
455                         &len );
456 
457                 /*
458                  * not much else we can do here, lets assume that
459                  * there is enough space
460                  */
461 
462                 if ( ptr != value )
463                 {
464                     SQLWCHAR *s1;
465 
466                     s1 = ansi_to_unicode_alloc( value, SQL_NTS, connection, NULL );
467 
468                     if ( s1 )
469                     {
470                         wide_strcpy( value, s1 );
471                         free( s1 );
472                     }
473 
474                     /*
475                      * are we still here ? good
476                      */
477                 }
478             }
479             else
480             {
481                 __post_internal_error( &connection -> error,
482                         ERROR_IM001, NULL,
483                         connection -> environment -> requested_version );
484 
485                 return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
486             }
487         }
488 
489         if ( log_info.log_flag )
490         {
491             sprintf( connection -> msg,
492                     "\n\t\tExit:[%s]",
493                         __get_return_status( ret, s1 ));
494 
495             dm_log_write( __FILE__,
496                     __LINE__,
497                     LOG_INFO,
498                     LOG_INFO,
499                     connection -> msg );
500         }
501 
502         return function_return( SQL_HANDLE_DBC, connection, ret, DEFER_R3 );
503     }
504 }
505