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: SQLDataSourcesW.c,v 1.6 2009/02/18 17:59:08 lurcher Exp $
31 *
32 * $Log: SQLDataSourcesW.c,v $
33 * Revision 1.6 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.5 2003/10/30 18:20:45 lurcher
37 *
38 * Fix broken thread protection
39 * Remove SQLNumResultCols after execute, lease S4/S% to driver
40 * Fix string overrun in SQLDriverConnect
41 * Add initial support for Interix
42 *
43 * Revision 1.4 2002/12/05 17:44:30 lurcher
44 *
45 * Display unknown return values in return logging
46 *
47 * Revision 1.3 2002/07/24 08:49:51 lurcher
48 *
49 * Alter UNICODE support to use iconv for UNICODE-ANSI conversion
50 *
51 * Revision 1.2 2001/12/13 13:00:32 lurcher
52 *
53 * Remove most if not all warnings on 64 bit platforms
54 * Add support for new MS 3.52 64 bit changes
55 * Add override to disable the stopping of tracing
56 * Add MAX_ROWS support in postgres driver
57 *
58 * Revision 1.1.1.1 2001/10/17 16:40:05 lurcher
59 *
60 * First upload to SourceForge
61 *
62 * Revision 1.3 2001/04/12 17:43:36 nick
63 *
64 * Change logging and added autotest to odbctest
65 *
66 * Revision 1.2 2001/01/04 13:16:25 nick
67 *
68 * Add support for GNU portable threads and tidy up some UNICODE compile
69 * warnings
70 *
71 * Revision 1.1 2000/12/31 20:30:54 nick
72 *
73 * Add UNICODE support
74 *
75 *
76 **********************************************************************/
77
78#include <config.h>
79#include "drivermanager.h"
80
81static char const rcsid[]= "$RCSfile: SQLDataSourcesW.c,v $";
82
83#define BUFFERSIZE 1024 * 4
84
85SQLRETURN SQLDataSourcesW( SQLHENV environment_handle,
86 SQLUSMALLINT direction,
87 SQLWCHAR *server_name,
88 SQLSMALLINT buffer_length1,
89 SQLSMALLINT *name_length1,
90 SQLWCHAR *description,
91 SQLSMALLINT buffer_length2,
92 SQLSMALLINT *name_length2 )
93{
94 DMHENV environment = (DMHENV) environment_handle;
95 SQLRETURN ret;
96 char buffer[ BUFFERSIZE + 1 ];
97 char object[ INI_MAX_OBJECT_NAME + 1 ];
98 char property[ INI_MAX_PROPERTY_VALUE + 1 ];
99 char driver[ INI_MAX_PROPERTY_VALUE + 1 ];
100 SQLCHAR s1[ 100 + LOG_MESSAGE_LEN ];
101
102 if ( !__validate_env( environment ))
103 {
104 dm_log_write( __FILE__,
105 __LINE__,
106 LOG_INFO,
107 LOG_INFO,
108 "Error: SQL_INVALID_HANDLE" );
109
110 return SQL_INVALID_HANDLE;
111 }
112
113 function_entry( environment );
114
115 if ( log_info.log_flag )
116 {
117 sprintf( environment -> msg, "\n\t\tEntry:\
118\n\t\t\tEnvironment = %p",
119 environment );
120
121 dm_log_write( __FILE__,
122 __LINE__,
123 LOG_INFO,
124 LOG_INFO,
125 environment -> msg );
126 }
127
128 thread_protect( SQL_HANDLE_ENV, environment );
129
130 /*
131 * check that a version has been requested
132 */
133
134 if ( environment -> requested_version == 0 )
135 {
136 dm_log_write( __FILE__,
137 __LINE__,
138 LOG_INFO,
139 LOG_INFO,
140 "Error: HY010" );
141
142 __post_internal_error( &environment -> error,
143 ERROR_HY010, NULL,
144 environment -> requested_version );
145
146 return function_return_nodrv( SQL_HANDLE_ENV, environment, SQL_ERROR );
147 }
148
149 if ( buffer_length1 < 0 || buffer_length2 < 0 )
150 {
151 dm_log_write( __FILE__,
152 __LINE__,
153 LOG_INFO,
154 LOG_INFO,
155 "Error: HY090" );
156
157 __post_internal_error( &environment -> error,
158 ERROR_HY090, NULL,
159 environment -> requested_version );
160
161 return function_return_nodrv( SQL_HANDLE_ENV, environment, SQL_ERROR );
162 }
163
164 if ( direction != SQL_FETCH_FIRST &&
165 direction != SQL_FETCH_FIRST_USER &&
166 direction != SQL_FETCH_FIRST_SYSTEM &&
167 direction != SQL_FETCH_NEXT )
168 {
169 dm_log_write( __FILE__,
170 __LINE__,
171 LOG_INFO,
172 LOG_INFO,
173 "Error: HY103" );
174
175 __post_internal_error( &environment -> error,
176 ERROR_HY103, NULL,
177 environment -> requested_version );
178
179 return function_return_nodrv( SQL_HANDLE_ENV, environment, SQL_ERROR );
180 }
181
182 /*
183 * for this function USER = "~/.odbc.ini" and
184 * SYSTEM = "/usr/odbc.ini
185 */
186
187 if ( direction == SQL_FETCH_FIRST )
188 {
189 environment -> fetch_mode = ODBC_BOTH_DSN;
190 environment -> entry = 0;
191 }
192 else if ( direction == SQL_FETCH_FIRST_USER )
193 {
194 environment -> fetch_mode = ODBC_USER_DSN;
195 environment -> entry = 0;
196 }
197 else if ( direction == SQL_FETCH_FIRST_SYSTEM )
198 {
199 environment -> fetch_mode = ODBC_SYSTEM_DSN;
200 environment -> entry = 0;
201 }
202
203 /*
204 * this is lifted from Peters code
205 */
206
207 memset( buffer, 0, sizeof( buffer ));
208 memset( object, 0, sizeof( object ));
209 SQLSetConfigMode( environment -> fetch_mode );
210
211 SQLGetPrivateProfileString( NULL, NULL, NULL,
212 buffer, sizeof( buffer ),
213 "odbc.ini" );
214
215 if ( iniElement( buffer, '\0', '\0',
216 environment -> entry,
217 object, sizeof( object )) != INI_SUCCESS )
218 {
219 environment -> entry = 0;
220 ret = SQL_NO_DATA;
221 }
222 else
223 {
224 memset( buffer, 0, sizeof( buffer ));
225 memset( property, 0, sizeof( property ));
226 memset( driver, 0, sizeof( driver ));
227
228 SQLGetPrivateProfileString( object, "Driver", "",
229 driver, sizeof( driver ), "odbc.ini" );
230
231 if ( strlen( driver ) > 0 )
232 {
233 /*
234 SQLGetPrivateProfileString( driver, "Description", "",
235 property, sizeof( property ), "odbcinst.ini" );
236 */
237 strcpy( property, driver );
238 }
239 else
240 {
241 strcpy( property, "" );
242 }
243
244 environment -> entry++;
245
246 if (( server_name && buffer_length1 <= strlen( object )) ||
247 ( description && buffer_length2 <= strlen( property )))
248 {
249 __post_internal_error( &environment -> error,
250 ERROR_01004, NULL,
251 environment -> requested_version );
252 ret = SQL_SUCCESS_WITH_INFO;
253 }
254 else
255 {
256 ret = SQL_SUCCESS;
257 }
258
259 if ( server_name )
260 {
261 SQLWCHAR *s1;
262
263 s1 = ansi_to_unicode_alloc((SQLCHAR*) object, SQL_NTS, NULL, NULL );
264
265 if ( s1 )
266 {
267 if ( buffer_length1 <= strlen( object ))
268 {
269 memcpy( server_name, s1, buffer_length1 * 2 );
270 server_name[ buffer_length1 - 1 ] = 0;
271 }
272 else
273 {
274 wide_strcpy( server_name, s1 );
275 }
276
277 free( s1 );
278 }
279 }
280
281 if ( description )
282 {
283 SQLWCHAR *s1;
284
285 s1 = ansi_to_unicode_alloc((SQLCHAR*) property, SQL_NTS, NULL, NULL );
286
287 if ( s1 )
288 {
289 if ( buffer_length2 <= strlen( property ))
290 {
291 memcpy( description, s1, buffer_length2 * 2 );
292 description[ buffer_length1 - 1 ] = 0;
293 }
294 else
295 {
296 wide_strcpy( description, s1 );
297 }
298
299 free( s1 );
300 }
301 }
302
303 if ( name_length1 )
304 {
305 *name_length1 = strlen( object );
306 }
307 if ( name_length2 )
308 {
309 *name_length2 = strlen( property );
310 }
311 }
312
313 /* NEVER FORGET TO RESET THIS TO ODBC_BOTH_DSN */
314 SQLSetConfigMode( ODBC_BOTH_DSN );
315
316 if ( log_info.log_flag )
317 {
318 sprintf( environment -> msg,
319 "\n\t\tExit:[%s]",
320 __get_return_status( SQL_SUCCESS, s1 ));
321
322 dm_log_write( __FILE__,
323 __LINE__,
324 LOG_INFO,
325 LOG_INFO,
326 environment -> msg );
327 }
328
329 return function_return_nodrv( SQL_HANDLE_ENV, environment, ret );
330}
331