1/* 2 * dlproc.c 3 * 4 * $Id: dlproc.c,v 1.14 2006/01/20 15:58:34 source Exp $ 5 * 6 * Load driver and resolve driver's function entry point 7 * 8 * The iODBC driver manager. 9 * 10 * Copyright (C) 1995 by Ke Jin <kejin@empress.com> 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#include <iodbc.h> 80 81#include <sql.h> 82#include <sqlext.h> 83 84#include <dlproc.h> 85 86#include <herr.h> 87#include <henv.h> 88#include <hdbc.h> 89 90#include <itrace.h> 91 92char *odbcapi_symtab[] = 93{ 94 "UNKNOWN FUNCTION" 95#define FUNCDEF(A, B, C) ,C 96#include "henv.ci" 97#undef FUNCDEF 98}; 99 100 101HPROC 102_iodbcdm_getproc (HDBC hdbc, int idx) 103{ 104 CONN (pdbc, hdbc); 105 ENV_t *penv; 106 HPROC *phproc; 107 108 if (idx <= 0 || idx >= __LAST_API_FUNCTION__) 109 return SQL_NULL_HPROC; 110 111 penv = (ENV_t *) (pdbc->henv); 112 113 if (penv == NULL) 114 return SQL_NULL_HPROC; 115 116 phproc = penv->dllproc_tab + idx; 117 118 if (*phproc == SQL_NULL_HPROC) 119 *phproc = _iodbcdm_dllproc (penv->hdll, odbcapi_symtab[idx]); 120 121 return *phproc; 122} 123 124 125static dlproc_t *pRoot = NULL; 126 127 128HDLL 129_iodbcdm_dllopen (char *path) 130{ 131 dlproc_t *pDrv = NULL, *p; 132 133 /* 134 * Check if we have already loaded the driver 135 */ 136 for (p = pRoot; p; p = p->next) 137 { 138 if (STREQ (p->path, path)) 139 { 140 pDrv = p; 141 break; 142 } 143 } 144 145 /* 146 * If already loaded, increase ref counter 147 */ 148 if (pDrv) 149 { 150 pDrv->refcount++; 151 152 /* 153 * If the driver was unloaded, load it again 154 */ 155 if (pDrv->dll == NULL) 156 pDrv->dll = (HDLL) DLL_OPEN (path); 157 158 return pDrv->dll; 159 } 160 161 /* 162 * Initialize new structure 163 */ 164 if ((pDrv = calloc (1, sizeof (dlproc_t))) == NULL) 165 return NULL; 166 167 pDrv->refcount = 1; 168 pDrv->path = STRDUP (path); 169 pDrv->dll = (HDLL) DLL_OPEN (path); 170 171 /* 172 * Add to linked list 173 */ 174 pDrv->next = pRoot; 175 pRoot = pDrv; 176 177 return pDrv->dll; 178} 179 180 181HPROC 182_iodbcdm_dllproc (HDLL hdll, char *sym) 183{ 184 return (HPROC) DLL_PROC (hdll, sym); 185} 186 187 188int 189_iodbcdm_dllclose (HDLL hdll) 190{ 191 dlproc_t *pDrv = NULL, *p; 192 193 /* 194 * Find loaded driver 195 */ 196 for (p = pRoot; p; p = p->next) 197 { 198 if (p->dll == hdll) 199 { 200 pDrv = p; 201 break; 202 } 203 } 204 205 /* 206 * Not found 207 */ 208 if (!pDrv) 209 return -1; 210 211 /* 212 * Decrease reference counter 213 */ 214 pDrv->refcount--; 215 216 /* 217 * Check if it is possible to unload the driver safely 218 * 219 * NOTE: Some drivers set explicit on_exit hooks, which makes it 220 * impossible for the driver manager to unload the driver 221 * as this would crash the executable at exit. 222 */ 223 if (pDrv->refcount == 0 && pDrv->safe_unload) 224 { 225 DLL_CLOSE (pDrv->dll); 226 pDrv->dll = NULL; 227 } 228 229 return 0; 230} 231 232 233char * 234_iodbcdm_dllerror () 235{ 236 return DLL_ERROR (); 237} 238 239 240/* 241 * If driver manager determines this driver is safe, flag the driver can 242 * be unloaded if not used. 243 */ 244void 245_iodbcdm_safe_unload (HDLL hdll) 246{ 247 dlproc_t *pDrv = NULL, *p; 248 249 /* 250 * Find loaded driver 251 */ 252 for (p = pRoot; p; p = p->next) 253 { 254 if (p->dll == hdll) 255 { 256 pDrv = p; 257 break; 258 } 259 } 260 261 /* 262 * Driver not found 263 */ 264 if (!pDrv) 265 return; 266 267 pDrv->safe_unload = 1; 268} 269