1/* 2 * SQLConfigDriver.c 3 * 4 * $Id: SQLConfigDriver.c,v 1.12 2006/01/20 15:58:35 source Exp $ 5 * 6 * Load the appropriate driver setup DLL and calls the ConfigDriver 7 * function. 8 * 9 * The iODBC driver manager. 10 * 11 * Copyright (C) 1996-2006 by OpenLink Software <iodbc@openlinksw.com> 12 * All Rights Reserved. 13 * 14 * This software is released under the terms of either of the following 15 * licenses: 16 * 17 * - GNU Library General Public License (see LICENSE.LGPL) 18 * - The BSD License (see LICENSE.BSD). 19 * 20 * Note that the only valid version of the LGPL license as far as this 21 * project is concerned is the original GNU Library General Public License 22 * Version 2, dated June 1991. 23 * 24 * While not mandated by the BSD license, any patches you make to the 25 * iODBC source code may be contributed back into the iODBC project 26 * at your discretion. Contributions will benefit the Open Source and 27 * Data Access community as a whole. Submissions may be made at: 28 * 29 * http://www.iodbc.org 30 * 31 * 32 * GNU Library Generic Public License Version 2 33 * ============================================ 34 * This library is free software; you can redistribute it and/or 35 * modify it under the terms of the GNU Library General Public 36 * License as published by the Free Software Foundation; only 37 * Version 2 of the License dated June 1991. 38 * 39 * This library is distributed in the hope that it will be useful, 40 * but WITHOUT ANY WARRANTY; without even the implied warranty of 41 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 42 * Library General Public License for more details. 43 * 44 * You should have received a copy of the GNU Library General Public 45 * License along with this library; if not, write to the Free 46 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 47 * 48 * 49 * The BSD License 50 * =============== 51 * Redistribution and use in source and binary forms, with or without 52 * modification, are permitted provided that the following conditions 53 * are met: 54 * 55 * 1. Redistributions of source code must retain the above copyright 56 * notice, this list of conditions and the following disclaimer. 57 * 2. Redistributions in binary form must reproduce the above copyright 58 * notice, this list of conditions and the following disclaimer in 59 * the documentation and/or other materials provided with the 60 * distribution. 61 * 3. Neither the name of OpenLink Software Inc. nor the names of its 62 * contributors may be used to endorse or promote products derived 63 * from this software without specific prior written permission. 64 * 65 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 66 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 67 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 68 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OPENLINK OR 69 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 70 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 71 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 72 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 73 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 74 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 75 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 76 */ 77 78 79 80#include <iodbc.h> 81#include <odbcinst.h> 82#include <unicode.h> 83 84#if defined (__APPLE__) && !(defined (NO_FRAMEWORKS) || defined (_LP64)) 85# include <Carbon/Carbon.h> 86#endif 87 88#include "dlf.h" 89#include "inifile.h" 90#include "misc.h" 91#include "iodbc_error.h" 92 93#ifndef WIN32 94#include <unistd.h> 95#define CALL_CONFIG_DRIVER(driverpath) \ 96 if ((handle = DLL_OPEN((driverpath))) != NULL) \ 97 { \ 98 if ((pConfigDriver = (pConfigDriverFunc)DLL_PROC(handle, "ConfigDriver")) != NULL) \ 99 { \ 100 if (pConfigDriver (hwndParent, fRequest, lpszDriver, lpszArgs, lpszMsg, cbMsgMax, pcbMsgOut)) \ 101 { \ 102 DLL_CLOSE(handle); \ 103 retcode = TRUE; \ 104 goto done; \ 105 } \ 106 else \ 107 { \ 108 PUSH_ERROR(ODBC_ERROR_REQUEST_FAILED); \ 109 DLL_CLOSE(handle); \ 110 retcode = FALSE; \ 111 goto done; \ 112 } \ 113 } \ 114 DLL_CLOSE(handle); \ 115 } 116 117#define CALL_CONFIG_DRIVERW(driverpath) \ 118 if ((handle = DLL_OPEN((driverpath))) != NULL) \ 119 { \ 120 if ((pConfigDriverW = (pConfigDriverWFunc)DLL_PROC(handle, "ConfigDriverW")) != NULL) \ 121 { \ 122 if (pConfigDriverW (hwndParent, fRequest, (SQLWCHAR*)lpszDriver, (SQLWCHAR*)lpszArgs, (SQLWCHAR*)lpszMsg, cbMsgMax, pcbMsgOut)) \ 123 { \ 124 DLL_CLOSE(handle); \ 125 retcode = TRUE; \ 126 goto done; \ 127 } \ 128 else \ 129 { \ 130 PUSH_ERROR(ODBC_ERROR_REQUEST_FAILED); \ 131 DLL_CLOSE(handle); \ 132 retcode = FALSE; \ 133 goto done; \ 134 } \ 135 } \ 136 else if ((pConfigDriver = (pConfigDriverFunc)DLL_PROC(handle, "ConfigDriver")) != NULL) \ 137 { \ 138 char *_args_u8 = (char *) dm_SQL_WtoU8((SQLWCHAR*)lpszArgs, SQL_NTS); \ 139 char *_msg_u8 = (char *) dm_SQL_WtoU8((SQLWCHAR*)lpszMsg, SQL_NTS); \ 140 if ((_args_u8 == NULL && lpszArgs) || (_msg_u8 == NULL && lpszMsg)) \ 141 { \ 142 PUSH_ERROR (ODBC_ERROR_OUT_OF_MEM); \ 143 DLL_CLOSE(handle); \ 144 retcode = FALSE; \ 145 goto done; \ 146 } \ 147 if (pConfigDriver (hwndParent, fRequest, _drv_u8, _args_u8, _msg_u8, STRLEN(_msg_u8), pcbMsgOut)) \ 148 { \ 149 MEM_FREE (_args_u8); \ 150 MEM_FREE (_msg_u8); \ 151 DLL_CLOSE(handle); \ 152 retcode = TRUE; \ 153 goto done; \ 154 } \ 155 else \ 156 { \ 157 MEM_FREE (_args_u8); \ 158 MEM_FREE (_msg_u8); \ 159 PUSH_ERROR(ODBC_ERROR_REQUEST_FAILED); \ 160 DLL_CLOSE(handle); \ 161 retcode = FALSE; \ 162 goto done; \ 163 } \ 164 } \ 165 DLL_CLOSE(handle); \ 166 } 167#endif 168 169BOOL INSTAPI 170SQLConfigDriver_Internal (HWND hwndParent, WORD fRequest, LPCSTR lpszDriver, 171 LPCSTR lpszArgs, LPSTR lpszMsg, WORD cbMsgMax, WORD FAR * pcbMsgOut, 172 SQLCHAR waMode) 173{ 174 PCONFIG pCfg; 175 BOOL retcode = FALSE; 176 void *handle; 177 pConfigDriverFunc pConfigDriver; 178 pConfigDriverWFunc pConfigDriverW; 179#if defined (__APPLE__) && !(defined (NO_FRAMEWORKS) || defined (_LP64)) 180 CFStringRef libname = NULL; 181 CFBundleRef bundle; 182 CFURLRef liburl; 183 char name[1024] = { 0 }; 184#endif 185 char *_drv_u8 = NULL; 186 187 /* Check input parameters */ 188 CLEAR_ERROR (); 189 190 if (waMode == 'W') 191 { 192 _drv_u8 = (char *) dm_SQL_WtoU8 ((SQLWCHAR *) lpszDriver, SQL_NTS); 193 if (_drv_u8 == NULL && lpszDriver) 194 { 195 PUSH_ERROR (ODBC_ERROR_OUT_OF_MEM); 196 goto quit; 197 } 198 } 199 else 200 _drv_u8 = (char *) lpszDriver; 201 202 if (!_drv_u8 || !STRLEN (_drv_u8)) 203 { 204 PUSH_ERROR (ODBC_ERROR_INVALID_NAME); 205 goto quit; 206 } 207 208 /* Map the request User/System */ 209 if (fRequest < ODBC_INSTALL_DRIVER || fRequest > ODBC_CONFIG_DRIVER_MAX) 210 { 211 PUSH_ERROR (ODBC_ERROR_INVALID_REQUEST_TYPE); 212 goto quit; 213 } 214 215 /* Get it from the user odbcinst file */ 216 wSystemDSN = USERDSN_ONLY; 217 if (!_iodbcdm_cfg_search_init (&pCfg, "odbcinst.ini", TRUE)) 218 { 219 if (!_iodbcdm_cfg_find (pCfg, (char *) _drv_u8, "Setup")) 220 { 221 if (waMode == 'A') 222 { 223 CALL_CONFIG_DRIVER (pCfg->value); 224 } 225 else 226 { 227 CALL_CONFIG_DRIVERW (pCfg->value); 228 } 229 } 230 if (!_iodbcdm_cfg_find (pCfg, (char *) _drv_u8, "Driver")) 231 { 232 if (waMode == 'A') 233 { 234 CALL_CONFIG_DRIVER (pCfg->value); 235 } 236 else 237 { 238 CALL_CONFIG_DRIVERW (pCfg->value); 239 } 240 } 241 if (!access (_drv_u8, X_OK)) 242 { 243 if (waMode == 'A') 244 { 245 CALL_CONFIG_DRIVER (_drv_u8); 246 } 247 else 248 { 249 CALL_CONFIG_DRIVERW (_drv_u8); 250 } 251 } 252 if (!_iodbcdm_cfg_find (pCfg, "Default", "Setup")) 253 { 254 if (waMode == 'A') 255 { 256 CALL_CONFIG_DRIVER (pCfg->value); 257 } 258 else 259 { 260 CALL_CONFIG_DRIVERW (pCfg->value); 261 } 262 } 263 if (!_iodbcdm_cfg_find (pCfg, "Default", "Driver")) 264 { 265 if (waMode == 'A') 266 { 267 CALL_CONFIG_DRIVER (pCfg->value); 268 } 269 else 270 { 271 CALL_CONFIG_DRIVERW (pCfg->value); 272 } 273 } 274 } 275 276 /* Get it from the system odbcinst file */ 277 if (pCfg) 278 { 279 _iodbcdm_cfg_done (pCfg); 280 pCfg = NULL; 281 } 282 wSystemDSN = SYSTEMDSN_ONLY; 283 if (!_iodbcdm_cfg_search_init (&pCfg, "odbcinst.ini", TRUE)) 284 { 285 if (!_iodbcdm_cfg_find (pCfg, (char *) _drv_u8, "Setup")) 286 { 287 if (waMode == 'A') 288 { 289 CALL_CONFIG_DRIVER (pCfg->value); 290 } 291 else 292 { 293 CALL_CONFIG_DRIVERW (pCfg->value); 294 } 295 } 296 if (!_iodbcdm_cfg_find (pCfg, (char *) _drv_u8, "Driver")) 297 { 298 if (waMode == 'A') 299 { 300 CALL_CONFIG_DRIVER (pCfg->value); 301 } 302 else 303 { 304 CALL_CONFIG_DRIVERW (pCfg->value); 305 } 306 } 307 if (!access (_drv_u8, X_OK)) 308 { 309 if (waMode == 'A') 310 { 311 CALL_CONFIG_DRIVER (_drv_u8); 312 } 313 else 314 { 315 CALL_CONFIG_DRIVERW (_drv_u8); 316 } 317 } 318 if (!_iodbcdm_cfg_find (pCfg, "Default", "Setup")) 319 { 320 if (waMode == 'A') 321 { 322 CALL_CONFIG_DRIVER (pCfg->value); 323 } 324 else 325 { 326 CALL_CONFIG_DRIVERW (pCfg->value); 327 } 328 } 329 if (!_iodbcdm_cfg_find (pCfg, "Default", "Driver")) 330 { 331 if (waMode == 'A') 332 { 333 CALL_CONFIG_DRIVER (pCfg->value); 334 } 335 else 336 { 337 CALL_CONFIG_DRIVERW (pCfg->value); 338 } 339 } 340 } 341 342 /* The last ressort, a proxy driver */ 343#if defined (__APPLE__) && !(defined (NO_FRAMEWORKS) || defined (_LP64)) 344 bundle = CFBundleGetBundleWithIdentifier (CFSTR ("org.iodbc.inst")); 345 if (bundle) 346 { 347 /* Search for the drvproxy library */ 348 liburl = 349 CFBundleCopyResourceURL (bundle, CFSTR ("iODBCdrvproxy.bundle"), 350 NULL, NULL); 351 if (liburl 352 && (libname = 353 CFURLCopyFileSystemPath (liburl, kCFURLPOSIXPathStyle))) 354 { 355 CFStringGetCString (libname, name, sizeof (name), 356 kCFStringEncodingASCII); 357 strcat (name, "/Contents/MacOS/iODBCdrvproxy"); 358 if (waMode == 'A') 359 { 360 CALL_CONFIG_DRIVER (name); 361 } 362 else 363 { 364 CALL_CONFIG_DRIVERW (name); 365 } 366 } 367 if (liburl) 368 CFRelease (liburl); 369 if (libname) 370 CFRelease (libname); 371 } 372#else 373 if (waMode == 'A') 374 { 375 CALL_CONFIG_DRIVER ("libdrvproxy.so"); 376 } 377 else 378 { 379 CALL_CONFIG_DRIVERW ("libdrvproxy.so"); 380 } 381#endif 382 383 /* Error : ConfigDriver could no be found */ 384 PUSH_ERROR (ODBC_ERROR_LOAD_LIB_FAILED); 385 386done: 387 if (pCfg) 388 _iodbcdm_cfg_done (pCfg); 389 390quit: 391 if (_drv_u8 != lpszDriver) 392 MEM_FREE (_drv_u8); 393 394 wSystemDSN = USERDSN_ONLY; 395 configMode = ODBC_BOTH_DSN; 396 397 if (pcbMsgOut) 398 *pcbMsgOut = 0; 399 400 return retcode; 401} 402 403BOOL INSTAPI 404SQLConfigDriver (HWND hwndParent, WORD fRequest, LPCSTR lpszDriver, 405 LPCSTR lpszArgs, LPSTR lpszMsg, WORD cbMsgMax, WORD FAR * pcbMsgOut) 406{ 407 return SQLConfigDriver_Internal (hwndParent, fRequest, 408 (SQLPOINTER) lpszDriver, (SQLPOINTER) lpszArgs, (SQLPOINTER) lpszMsg, 409 cbMsgMax, pcbMsgOut, 'A'); 410} 411 412BOOL INSTAPI 413SQLConfigDriverW (HWND hwndParent, WORD fRequest, LPCWSTR lpszDriver, 414 LPCWSTR lpszArgs, LPWSTR lpszMsg, WORD cbMsgMax, WORD FAR * pcbMsgOut) 415{ 416 return SQLConfigDriver_Internal (hwndParent, fRequest, 417 (SQLPOINTER) lpszDriver, (SQLPOINTER) lpszArgs, (SQLPOINTER) lpszMsg, 418 cbMsgMax, pcbMsgOut, 'W'); 419} 420