1/**************************************************
2 * SQLConfigDriver
3 *
4 **************************************************
5 * This code was created by Peter Harvey @ CodeByDesign.
6 * Released under LGPL 28.JAN.99
7 *
8 * Contributions from...
9 * -----------------------------------------------
10 * Peter Harvey - pharvey@codebydesign.com
11 **************************************************/
12#include <config.h>
13#include <odbcinstext.h>
14
15static BOOL SQLConfigDriverWide( HWND hWnd,
16 WORD nRequest,
17 LPCSTR pszDriver,
18 LPCSTR pszArgs,
19 LPSTR pszMsg,
20 WORD nMsgMax,
21 WORD *pnMsgOut,
22 LPCWSTR pszDriverW,
23 LPCWSTR pszArgsW,
24 LPWSTR pszMsgW,
25 int *iswide )
26{
27 BOOL nReturn;
28 void *hDLL;
29 BOOL (*pConfigDriver)( HWND, WORD, LPCSTR, LPCSTR, LPCSTR, WORD, WORD * );
30 BOOL (*pConfigDriverW)( HWND, WORD, LPCWSTR, LPCWSTR, LPCWSTR, WORD, WORD * );
31 char szDriverSetup[ODBC_FILENAME_MAX+1];
32 HINI hIni;
33 char szIniName[ ODBC_FILENAME_MAX * 2 + 1 ];
34 char b1[ ODBC_FILENAME_MAX + 1 ], b2[ ODBC_FILENAME_MAX + 1 ];
35
36 *iswide = 0;
37
38 /* SANITY CHECKS */
39 nReturn = FALSE;
40 if ( pszDriver == NULL )
41 {
42 inst_logPushMsg( __FILE__, __FILE__, __LINE__, LOG_CRITICAL, ODBC_ERROR_INVALID_NAME, "" );
43 return FALSE;
44 }
45 if ( nRequest > ODBC_CONFIG_DRIVER )
46 {
47 inst_logPushMsg( __FILE__, __FILE__, __LINE__, LOG_CRITICAL, ODBC_ERROR_INVALID_REQUEST_TYPE, "" );
48 return FALSE;
49 }
50
51 /* OK */
52
53#ifdef VMS
54 sprintf( szIniName, "%s:%s", odbcinst_system_file_path( b1 ), odbcinst_system_file_name( b2 ));
55#else
56 sprintf( szIniName, "%s/%s", odbcinst_system_file_path( b1 ), odbcinst_system_file_name( b2 ));
57#endif
58
59 /* lets get driver setup file name from odbcinst.ini */
60#ifdef __OS2__
61 if ( iniOpen( &hIni, szIniName, "#;", '[', ']', '=', TRUE, 1L ) != INI_SUCCESS )
62#else
63 if ( iniOpen( &hIni, szIniName, "#;", '[', ']', '=', TRUE ) != INI_SUCCESS )
64#endif
65 {
66 inst_logPushMsg( __FILE__, __FILE__, __LINE__, LOG_CRITICAL, ODBC_ERROR_INVALID_NAME, "" );
67 return FALSE;
68 }
69
70#ifdef PLATFORM64
71 if ( iniPropertySeek( hIni, (char *)pszDriver, "Setup64", "" ) == INI_SUCCESS ||
72 iniPropertySeek( hIni, (char *)pszDriver, "Setup", "" ) == INI_SUCCESS )
73#else
74 if ( iniPropertySeek( hIni, (char *)pszDriver, "Setup", "" ) != INI_SUCCESS )
75#endif
76 {
77 inst_logPushMsg( __FILE__, __FILE__, __LINE__, LOG_CRITICAL, ODBC_ERROR_INVALID_NAME, "" );
78 iniClose( hIni );
79 return FALSE;
80 }
81 iniValue( hIni, szDriverSetup );
82 iniClose( hIni );
83
84 /*
85 * initialize libtool
86 */
87
88 lt_dlinit();
89
90 /* process request */
91 switch ( nRequest )
92 {
93 case ODBC_CONFIG_DRIVER:
94 /* WHAT OPTIONS CAN WE EXPECT IN pszArgs??
95 * Sounds like just connection pooling options
96 * In anycase, the spec says handle this in the
97 * odbcinst so we probably want to make some calls here...
98 * How common are Driver config options (not DSN options) anyway?
99 * - Peter
100 */
101 break;
102 case ODBC_INSTALL_DRIVER:
103 case ODBC_REMOVE_DRIVER:
104 default : /* DRIVER SEPCIFIC are default; HANDLE AS PER INSTALL & REMOVE */
105 /* errors in here are ignored, according to the spec; perhaps I should ret error and let app ignore? */
106 if ( (hDLL = lt_dlopen( szDriverSetup )) )
107 {
108 pConfigDriver = (BOOL (*)(HWND, WORD, LPCSTR, LPCSTR, LPCSTR, WORD, WORD * )) lt_dlsym( hDLL, "ConfigDriver" );
109 pConfigDriverW = (BOOL (*)(HWND, WORD, LPCWSTR, LPCWSTR, LPCWSTR, WORD, WORD * )) lt_dlsym( hDLL, "ConfigDriverW" );
110/* if ( lt_dlerror() == NULL ) */
111 if ( pConfigDriver )
112 nReturn = pConfigDriver( hWnd, nRequest, pszDriver, pszArgs, pszMsg, nMsgMax, pnMsgOut);
113 else if ( pConfigDriverW )
114 {
115 nReturn = pConfigDriverW( hWnd, nRequest, pszDriverW, pszArgsW, pszMsgW, nMsgMax, pnMsgOut);
116 *iswide = 1;
117 }
118 else
119 inst_logPushMsg( __FILE__, __FILE__, __LINE__, LOG_CRITICAL, ODBC_ERROR_GENERAL_ERR, "" );
120 }
121 else
122 inst_logPushMsg( __FILE__, __FILE__, __LINE__, LOG_CRITICAL, ODBC_ERROR_GENERAL_ERR, "" );
123 }
124
125 return TRUE;
126}
127
128BOOL INSTAPI SQLConfigDriver(HWND hwndParent,
129 WORD fRequest,
130 LPCSTR lpszDriver,
131 LPCSTR lpszArgs,
132 LPSTR lpszMsg,
133 WORD cbMsgMax,
134 WORD *pcbMsgOut)
135{
136 SQLWCHAR *drv;
137 SQLWCHAR *args;
138 SQLWCHAR *msg;
139 BOOL ret;
140 WORD len;
141 int iswide;
142
143 inst_logClear();
144
145 drv = lpszDriver ? _single_string_alloc_and_expand( lpszDriver ) : (SQLWCHAR*)NULL;
146 args = lpszArgs ? _multi_string_alloc_and_expand( lpszArgs ) : (SQLWCHAR*)NULL;
147
148 if ( lpszMsg )
149 {
150 if ( cbMsgMax > 0 )
151 {
152 msg = calloc( cbMsgMax + 1, sizeof( SQLWCHAR ));
153 }
154 else
155 {
156 msg = NULL;
157 }
158 }
159 else
160 {
161 msg = NULL;
162 }
163
164 ret = SQLConfigDriverWide( hwndParent,
165 fRequest,
166 lpszDriver,
167 lpszArgs,
168 lpszMsg,
169 cbMsgMax,
170 &len,
171 drv,
172 args,
173 msg,
174 &iswide );
175
176 if ( drv )
177 free( drv );
178 if ( args )
179 free( args );
180
181 if ( iswide )
182 {
183 if ( ret && msg )
184 {
185 _single_copy_from_wide((SQLCHAR*) lpszMsg, msg, len + 1 );
186 }
187 }
188 else
189 {
190 /*
191 * the output is already in the right buffer
192 */
193 }
194
195 if ( msg )
196 free( msg );
197
198 if ( pcbMsgOut )
199 *pcbMsgOut = len;
200
201 return ret;
202}
203
204BOOL INSTAPI SQLConfigDriverW(HWND hwndParent,
205 WORD fRequest,
206 LPCWSTR lpszDriver,
207 LPCWSTR lpszArgs,
208 LPWSTR lpszMsg,
209 WORD cbMsgMax,
210 WORD *pcbMsgOut)
211{
212 char *drv;
213 char *args;
214 char *msg;
215 BOOL ret;
216 WORD len;
217 int iswide;
218
219 inst_logClear();
220
221 drv = lpszDriver ? _single_string_alloc_and_copy( lpszDriver ) : (char*)NULL;
222 args = lpszArgs ? _multi_string_alloc_and_copy( lpszArgs ) : (char*)NULL;
223
224 if ( lpszMsg )
225 {
226 if ( cbMsgMax > 0 )
227 {
228 msg = calloc( cbMsgMax + 1, 1 );
229 }
230 else
231 {
232 msg = NULL;
233 }
234 }
235 else
236 {
237 msg = NULL;
238 }
239
240 ret = SQLConfigDriverWide( hwndParent,
241 fRequest,
242 drv,
243 args,
244 msg,
245 cbMsgMax,
246 &len,
247 lpszDriver,
248 lpszArgs,
249 lpszMsg,
250 &iswide );
251
252 if ( drv )
253 free( drv );
254 if ( args )
255 free( args );
256
257 if ( iswide )
258 {
259 /*
260 * the output is already in the right buffer
261 */
262 }
263 else
264 {
265 if ( ret && msg )
266 {
267 _single_copy_to_wide( lpszMsg, msg, len + 1 );
268 }
269 }
270
271 if ( msg )
272 free( msg );
273
274 if ( pcbMsgOut )
275 *pcbMsgOut = len;
276
277 return ret;
278}
279