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 | |
81 | static char const rcsid[]= "$RCSfile: SQLDataSourcesW.c,v $" ; |
82 | |
83 | #define BUFFERSIZE 1024 * 4 |
84 | |
85 | SQLRETURN 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 | |