1/*
2 *  henv.c
3 *
4 *  $Id: henv.c,v 1.22 2006/07/10 13:49:29 source Exp $
5 *
6 *  Environment object management functions
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 <assert.h>
82#include <sql.h>
83#include <sqlext.h>
84
85#include <odbcinst.h>
86
87#include <dlproc.h>
88
89#include <herr.h>
90#include <henv.h>
91
92#include <itrace.h>
93
94/*
95 *  Use static initializer where possible
96 */
97
98#if defined (PTHREAD_MUTEX_INITIALIZER)
99SPINLOCK_DECLARE (iodbcdm_global_lock) = PTHREAD_MUTEX_INITIALIZER;
100#else
101SPINLOCK_DECLARE (iodbcdm_global_lock);
102#endif
103
104static int _iodbcdm_initialized = 0;
105
106
107static void
108_iodbcdm_env_settracing (GENV_t *genv)
109{
110  char buf[1024];
111
112  genv = genv; /*UNUSED*/
113
114  /*
115   *  Check TraceFile keyword
116   */
117  SQLSetConfigMode (ODBC_BOTH_DSN);
118  if( SQLGetPrivateProfileString ("ODBC", "TraceFile", "", buf, sizeof(buf) / sizeof(SQLTCHAR), "odbc.ini") == 0 || !buf[0])
119    STRCPY (buf, SQL_OPT_TRACE_FILE_DEFAULT);
120  trace_set_filename (buf);
121
122  /*
123   *  Check Trace keyword
124   */
125  SQLSetConfigMode (ODBC_BOTH_DSN);
126  if ( SQLGetPrivateProfileString ("ODBC", "Trace", "", buf, sizeof(buf) / sizeof(SQLTCHAR), "odbc.ini") &&
127      (STRCASEEQ (buf, "on") || STRCASEEQ (buf, "yes")
128   || STRCASEEQ (buf, "1")))
129    trace_start ();
130
131  return;
132}
133
134unsigned long _iodbc_env_counter = 0;
135
136SQLRETURN
137SQLAllocEnv_Internal (SQLHENV * phenv, int odbc_ver)
138{
139  GENV (genv, NULL);
140  int retcode = SQL_SUCCESS;
141
142  genv = (GENV_t *) MEM_ALLOC (sizeof (GENV_t));
143
144  if (genv == NULL)
145    {
146      *phenv = SQL_NULL_HENV;
147
148      return SQL_ERROR;
149    }
150  genv->rc = 0;
151
152  /*
153   *  Initialize this handle
154   */
155  genv->type = SQL_HANDLE_ENV;
156  genv->henv = SQL_NULL_HENV;	/* driver's env list */
157  genv->hdbc = SQL_NULL_HDBC;	/* driver's dbc list */
158  genv->herr = SQL_NULL_HERR;	/* err list          */
159#if (ODBCVER >= 0x300)
160  genv->odbc_ver = odbc_ver;
161  genv->connection_pooling = _iodbcdm_attr_connection_pooling;
162  genv->cp_match = SQL_CP_MATCH_DEFAULT;
163  genv->pdbc_pool = NULL;
164#endif
165  genv->err_rec = 0;
166
167  *phenv = (SQLHENV) genv;
168
169  /*
170   * Initialize tracing
171   */
172  if (++_iodbc_env_counter == 1)
173    _iodbcdm_env_settracing (genv);
174
175  return retcode;
176}
177
178
179SQLRETURN SQL_API
180SQLAllocEnv (SQLHENV * phenv)
181{
182  GENV (genv, NULL);
183  int retcode = SQL_SUCCESS;
184
185  /*
186   *  One time initialization
187   */
188  Init_iODBC();
189
190  ODBC_LOCK ();
191  retcode = SQLAllocEnv_Internal (phenv, SQL_OV_ODBC2);
192
193  genv = (GENV_t *) *phenv;
194
195  /*
196   * Start tracing
197   */
198  TRACE (trace_SQLAllocEnv (TRACE_ENTER, phenv));
199  TRACE (trace_SQLAllocEnv (TRACE_LEAVE, phenv));
200
201  ODBC_UNLOCK ();
202
203  return retcode;
204}
205
206
207extern void _iodbcdm_pool_drop_conn (HDBC hdbc, HDBC hdbc_prev);
208
209SQLRETURN
210SQLFreeEnv_Internal (SQLHENV henv)
211{
212  GENV (genv, henv);
213
214  if (!IS_VALID_HENV (genv))
215    {
216      return SQL_INVALID_HANDLE;
217    }
218  CLEAR_ERRORS (genv);
219
220  if (genv->hdbc != SQL_NULL_HDBC)
221    {
222      PUSHSQLERR (genv->herr, en_S1010);
223
224      return SQL_ERROR;
225    }
226
227#if (ODBCVER >= 0x300)
228  /* Drop connections from the pool */
229  while (genv->pdbc_pool != NULL)
230    _iodbcdm_pool_drop_conn (genv->pdbc_pool, NULL);
231#endif
232
233  /*
234   *  Invalidate this handle
235   */
236  genv->type = 0;
237
238  return SQL_SUCCESS;
239}
240
241
242SQLRETURN SQL_API
243SQLFreeEnv (SQLHENV henv)
244{
245  GENV (genv, henv);
246  int retcode = SQL_SUCCESS;
247
248  ODBC_LOCK ();
249
250  TRACE (trace_SQLFreeEnv (TRACE_ENTER, henv));
251
252  retcode = SQLFreeEnv_Internal (henv);
253
254  TRACE (trace_SQLFreeEnv (TRACE_LEAVE, henv));
255
256  MEM_FREE (genv);
257
258  /*
259   *  Close trace after last environment handle is freed
260   */
261  if (--_iodbc_env_counter == 0)
262    trace_stop();
263
264  ODBC_UNLOCK ();
265
266  return retcode;
267}
268
269
270/*
271 *  Initialize the system and let everyone wait until we have done so
272 *  properly
273 */
274void
275Init_iODBC (void)
276{
277#if !defined (PTHREAD_MUTEX_INITIALIZER) || defined (WINDOWS)
278  SPINLOCK_INIT (iodbcdm_global_lock);
279#endif
280
281  SPINLOCK_LOCK (iodbcdm_global_lock);
282  if (!_iodbcdm_initialized)
283    {
284      /*
285       *  OK, now flag we are not callable anymore
286       */
287      _iodbcdm_initialized = 1;
288
289      /*
290       *  Other one time initializations can be performed here
291       */
292    }
293  SPINLOCK_UNLOCK (iodbcdm_global_lock);
294
295  return;
296}
297
298
299void
300Done_iODBC(void)
301{
302#if !defined (PTHREAD_MUTEX_INITIALIZER) || defined (WINDOWS)
303    SPINLOCK_DONE (iodbcdm_global_lock);
304#endif
305}
306
307
308/*
309 *  DLL Entry points for Windows
310 */
311#if defined (WINDOWS)
312static int
313DLLInit (HINSTANCE hModule)
314{
315  Init_iODBC ();
316
317  return TRUE;
318}
319
320
321static void
322DLLExit (void)
323{
324  Done_iODBC ();
325}
326
327
328#pragma argused
329BOOL WINAPI
330DllMain (HINSTANCE hModule, DWORD fdReason, LPVOID lpvReserved)
331{
332  switch (fdReason)
333    {
334    case DLL_PROCESS_ATTACH:
335      if (!DLLInit (hModule))
336	return FALSE;
337      break;
338    case DLL_PROCESS_DETACH:
339      DLLExit ();
340    }
341  return TRUE;
342}
343#endif
344