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
95static char const rcsid[]= "$RCSfile: SQLGetConnectOptionW.c,v $";
96
97SQLRETURN 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 if ( log_info.log_flag )
114 {
115 *((SQLINTEGER*)value) = SQL_OPT_TRACE_ON;
116 }
117 else
118 {
119 *((SQLINTEGER*)value) = SQL_OPT_TRACE_ON;
120 }
121 }
122
123 return SQL_SUCCESS;
124 }
125 else if ( option == SQL_ATTR_TRACEFILE )
126 {
127 SQLRETURN ret = SQL_SUCCESS;
128
129 if ( log_info.log_file_name )
130 {
131 ansi_to_unicode_copy( value, log_info.log_file_name, SQL_NTS, connection, NULL );
132 }
133 else
134 {
135 ansi_to_unicode_copy( value, "", SQL_NTS, connection, NULL );
136 }
137 return ret;
138 }
139
140
141 /*
142 * check connection
143 */
144
145 if ( !__validate_dbc( connection ))
146 {
147 dm_log_write( __FILE__,
148 __LINE__,
149 LOG_INFO,
150 LOG_INFO,
151 "Error: SQL_INVALID_HANDLE" );
152
153#ifdef WITH_HANDLE_REDIRECT
154 {
155 DMHDBC parent_connection;
156
157 parent_connection = find_parent_handle( connection, SQL_HANDLE_DBC );
158
159 if ( parent_connection ) {
160 dm_log_write( __FILE__,
161 __LINE__,
162 LOG_INFO,
163 LOG_INFO,
164 "Info: found parent handle" );
165
166 if ( CHECK_SQLGETCONNECTOPTIONW( parent_connection ))
167 {
168 dm_log_write( __FILE__,
169 __LINE__,
170 LOG_INFO,
171 LOG_INFO,
172 "Info: calling redirected driver function" );
173
174 return SQLGETCONNECTOPTIONW( parent_connection,
175 connection,
176 option,
177 value );
178 }
179 }
180 }
181#endif
182 return SQL_INVALID_HANDLE;
183 }
184
185 function_entry( connection );
186
187 if ( log_info.log_flag )
188 {
189 sprintf( connection -> msg, "\n\t\tEntry:\
190\n\t\t\tConnection = %p\
191\n\t\t\tOption = %s\
192\n\t\t\tValue = %p",
193 connection,
194 __con_attr_as_string( s1, option ),
195 value );
196
197 dm_log_write( __FILE__,
198 __LINE__,
199 LOG_INFO,
200 LOG_INFO,
201 connection -> msg );
202 }
203
204 thread_protect( SQL_HANDLE_DBC, connection );
205
206 if ( connection -> state == STATE_C3 )
207 {
208 dm_log_write( __FILE__,
209 __LINE__,
210 LOG_INFO,
211 LOG_INFO,
212 "Error: HY010" );
213
214 __post_internal_error( &connection -> error,
215 ERROR_HY010, NULL,
216 connection -> environment -> requested_version );
217
218 return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
219 }
220
221 if ( connection -> state == STATE_C2 )
222 {
223 switch ( option )
224 {
225 case SQL_ACCESS_MODE:
226 case SQL_AUTOCOMMIT:
227 case SQL_LOGIN_TIMEOUT:
228 case SQL_ODBC_CURSORS:
229 break;
230
231 default:
232 dm_log_write( __FILE__,
233 __LINE__,
234 LOG_INFO,
235 LOG_INFO,
236 "Error: 08003" );
237
238 __post_internal_error( &connection -> error,
239 ERROR_08003, NULL,
240 connection -> environment -> requested_version );
241
242 return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
243 }
244 }
245
246 switch ( option )
247 {
248 case SQL_ACCESS_MODE:
249 /*
250 * if connected, call the driver
251 */
252 if ( connection -> state != STATE_C2 )
253 {
254 type = 0;
255 }
256 else
257 {
258 *((SQLINTEGER*)value) = connection -> access_mode;
259 type = 1;
260 }
261 break;
262
263 case SQL_AUTOCOMMIT:
264 /*
265 * if connected, call the driver
266 */
267 if ( connection -> state != STATE_C2 )
268 {
269 type = 0;
270 }
271 else
272 {
273 *((SQLINTEGER*)value) = connection -> auto_commit;
274 type = 1;
275 }
276 break;
277
278 case SQL_ODBC_CURSORS:
279 *((SQLINTEGER*)value) = connection -> cursors;
280 type = 1;
281 break;
282
283 case SQL_ATTR_LOGIN_TIMEOUT:
284 /*
285 * if connected, call the driver
286 */
287 if ( connection -> state != STATE_C2 )
288 {
289 type = 0;
290 }
291 else
292 {
293 *((SQLINTEGER*)value) = connection -> login_timeout;
294 type = 1;
295 }
296 break;
297
298
299 default:
300 break;
301 }
302
303 /*
304 * if type has been set we have already set the value,
305 * so just return
306 */
307 if ( type )
308 {
309 sprintf( connection -> msg,
310 "\n\t\tExit:[%s]",
311 __get_return_status( SQL_SUCCESS, s1 ));
312
313 dm_log_write( __FILE__,
314 __LINE__,
315 LOG_INFO,
316 LOG_INFO,
317 connection -> msg );
318
319 return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_SUCCESS );
320 }
321 else
322 {
323 SQLRETURN ret = 0;
324
325 /*
326 * call the driver
327 */
328 if ( connection -> unicode_driver ||
329 CHECK_SQLGETCONNECTOPTIONW( connection ) ||
330 CHECK_SQLGETCONNECTATTRW( connection ))
331 {
332 if ( CHECK_SQLGETCONNECTOPTIONW( connection ))
333 {
334 ret = SQLGETCONNECTOPTIONW( connection,
335 connection -> driver_dbc,
336 option,
337 value );
338 }
339 else if ( CHECK_SQLGETCONNECTATTRW( connection ))
340 {
341 SQLINTEGER length, len;
342 void * ptr;
343 SQLWCHAR txt[ 1024 ];
344
345 switch( option )
346 {
347 case SQL_ATTR_CURRENT_CATALOG:
348 case SQL_ATTR_TRACEFILE:
349 case SQL_ATTR_TRANSLATE_LIB:
350 length = sizeof( txt );
351 ptr = txt;
352 break;
353
354 default:
355 length = sizeof( SQLINTEGER );
356 ptr = value;
357 break;
358
359 }
360
361 ret = SQLGETCONNECTATTRW( connection,
362 connection -> driver_dbc,
363 option,
364 ptr,
365 length,
366 &len );
367
368 /*
369 * not much else we can do here, lets assume that
370 * there is enough space
371 */
372
373 if ( ptr != value )
374 {
375 wide_strcpy( value, ptr );
376
377 /*
378 * are we still here ? good
379 */
380 }
381 }
382 else
383 {
384 __post_internal_error( &connection -> error,
385 ERROR_IM001, NULL,
386 connection -> environment -> requested_version );
387
388 return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
389 }
390 }
391 else
392 {
393 if (( ret = CHECK_SQLGETCONNECTOPTION( connection )))
394 {
395 SQLCHAR *as1 = NULL;
396
397 switch( option )
398 {
399 case SQL_ATTR_CURRENT_CATALOG:
400 case SQL_ATTR_TRACEFILE:
401 case SQL_ATTR_TRANSLATE_LIB:
402 if ( SQL_SUCCEEDED( ret ) && value )
403 {
404 /*
405 * we need to chance out arm here, as we dont know
406 */
407
408 as1 = malloc( 1024 );
409 }
410 break;
411 }
412
413 ret = SQLGETCONNECTOPTION( connection,
414 connection -> driver_dbc,
415 option,
416 as1 ? as1 : value );
417
418 switch( option )
419 {
420 case SQL_ATTR_CURRENT_CATALOG:
421 case SQL_ATTR_TRACEFILE:
422 case SQL_ATTR_TRANSLATE_LIB:
423 if ( SQL_SUCCEEDED( ret ) && value && as1 )
424 {
425 ansi_to_unicode_copy( value, (char*) as1, SQL_NTS, connection, NULL );
426 }
427
428 if ( as1 )
429 {
430 free( as1 );
431 }
432 break;
433 }
434 }
435 else if ( CHECK_SQLGETCONNECTATTR( connection ))
436 {
437 SQLINTEGER length, len;
438 void * ptr;
439 char txt[ 1024 ];
440
441 switch( option )
442 {
443 case SQL_ATTR_CURRENT_CATALOG:
444 case SQL_ATTR_TRACEFILE:
445 case SQL_ATTR_TRANSLATE_LIB:
446 length = sizeof( txt );
447 ptr = txt;
448 break;
449
450 default:
451 length = sizeof( SQLINTEGER );
452 ptr = value;
453 break;
454
455 }
456
457 ret = SQLGETCONNECTATTR( connection,
458 connection -> driver_dbc,
459 option,
460 ptr,
461 length,
462 &len );
463
464 /*
465 * not much else we can do here, lets assume that
466 * there is enough space
467 */
468
469 if ( ptr != value )
470 {
471 SQLWCHAR *s1;
472
473 s1 = ansi_to_unicode_alloc( value, SQL_NTS, connection, NULL );
474
475 if ( s1 )
476 {
477 wide_strcpy( value, s1 );
478 free( s1 );
479 }
480
481 /*
482 * are we still here ? good
483 */
484 }
485 }
486 else
487 {
488 __post_internal_error( &connection -> error,
489 ERROR_IM001, NULL,
490 connection -> environment -> requested_version );
491
492 return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
493 }
494 }
495
496 if ( log_info.log_flag )
497 {
498 sprintf( connection -> msg,
499 "\n\t\tExit:[%s]",
500 __get_return_status( ret, s1 ));
501
502 dm_log_write( __FILE__,
503 __LINE__,
504 LOG_INFO,
505 LOG_INFO,
506 connection -> msg );
507 }
508
509 return function_return( SQL_HANDLE_DBC, connection, ret );
510 }
511}
512