Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
5 : : * This Source Code Form is subject to the terms of the Mozilla Public
6 : : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
11 : : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : : * contributor license agreements. See the NOTICE file distributed
13 : : * with this work for additional information regarding copyright
14 : : * ownership. The ASF licenses this file to you under the Apache
15 : : * License, Version 2.0 (the "License"); you may not use this file
16 : : * except in compliance with the License. You may obtain a copy of
17 : : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : : */
19 : :
20 : :
21 : : #include "odbcconfig.hxx"
22 : :
23 : : #ifdef SYSTEM_ODBC_HEADERS
24 : : #include <sqltypes.h>
25 : : #else
26 : : #include <odbc/sqltypes.h>
27 : : #endif
28 : :
29 : : #include <rtl/bootstrap.hxx>
30 : : #include <rtl/ustring.hxx>
31 : : #include <rtl/ustrbuf.hxx>
32 : : #include <osl/diagnose.h>
33 : : #include <osl/process.h>
34 : : #include <osl/thread.hxx>
35 : : #include <tools/debug.hxx>
36 : : #include <vcl/svapp.hxx>
37 : :
38 : : #ifdef HAVE_ODBC_SUPPORT
39 : :
40 : : #if defined WNT
41 : : #define ODBC_LIBRARY "ODBC32.DLL"
42 : : #define ODBC_UI_LIBRARY "ODBCCP32.DLL"
43 : : #endif
44 : : #ifdef UNX
45 : : #ifdef MACOSX
46 : : #define ODBC_LIBRARY "libiodbc.dylib"
47 : : #define ODBC_UI_LIBRARY "libiodbcinst.dylib"
48 : : #else
49 : : #define ODBC_LIBRARY_1 "libodbc.so.1"
50 : : #define ODBC_UI_LIBRARY_1 "libodbcinst.so.1"
51 : : #define ODBC_LIBRARY "libodbc.so"
52 : : #define ODBC_UI_LIBRARY "libodbcinst.so"
53 : : #endif
54 : : #endif
55 : :
56 : : // just to go with calling convention of windows
57 : : // so don't touch this
58 : : #if defined(WNT)
59 : : #undef SQL_API
60 : : #define SQL_API __stdcall
61 : : // At least under some circumstances, the below #include <odbc/sqlext.h> re-
62 : : // defines SQL_API to an empty string, leading to a compiler warning on MSC; to
63 : : // not break the current behavior, this is worked around by locally disabling
64 : : // that warning:
65 : : #if defined _MSC_VER
66 : : #pragma warning(push)
67 : : #pragma warning(disable: 4005)
68 : : #endif
69 : : #endif // defined(WNT)
70 : :
71 : : #ifdef SYSTEM_ODBC_HEADERS
72 : : #include <sqlext.h>
73 : : #else
74 : : #include <odbc/sqlext.h>
75 : : #endif
76 : :
77 : : #if defined(WNT)
78 : : #if defined _MSC_VER
79 : : #pragma warning(pop)
80 : : #endif
81 : : #undef SQL_API
82 : : #define SQL_API __stdcall
83 : : #endif // defined(WNT)
84 : : // from here on you can do what you want to
85 : :
86 : : #else
87 : :
88 : : #define ODBC_LIBRARY ""
89 : : #define ODBC_UI_LIBRARY ""
90 : :
91 : : #endif // HAVE_ODBC_SUPPORT
92 : :
93 : : //.........................................................................
94 : : namespace dbaui
95 : : {
96 : : //.........................................................................
97 : :
98 : :
99 : : #ifdef HAVE_ODBC_SUPPORT
100 : : typedef SQLRETURN (SQL_API* TSQLManageDataSource) (SQLHWND hwndParent);
101 : : typedef SQLRETURN (SQL_API* TSQLAllocHandle) (SQLSMALLINT HandleType, SQLHANDLE InputHandle, SQLHANDLE* OutputHandlePtr);
102 : : typedef SQLRETURN (SQL_API* TSQLFreeHandle) (SQLSMALLINT HandleType, SQLHANDLE Handle);
103 : : typedef SQLRETURN (SQL_API* TSQLSetEnvAttr) (SQLHENV EnvironmentHandle, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER StringLength);
104 : : typedef SQLRETURN (SQL_API* TSQLDataSources) (SQLHENV EnvironmentHandle, SQLUSMALLINT Direction, SQLCHAR* ServerName,
105 : : SQLSMALLINT BufferLength1, SQLSMALLINT* NameLength1Ptr, SQLCHAR* Description, SQLSMALLINT BufferLength2, SQLSMALLINT* NameLength2Ptr);
106 : :
107 : : #define NSQLManageDataSource(a) (*(TSQLManageDataSource)(m_pSQLManageDataSource))(a)
108 : : #define NSQLAllocHandle(a,b,c) (*(TSQLAllocHandle)(m_pAllocHandle))(a,b,c)
109 : : #define NSQLFreeHandle(a,b) (*(TSQLFreeHandle)(m_pFreeHandle))(a,b)
110 : : #define NSQLSetEnvAttr(a,b,c,d) (*(TSQLSetEnvAttr)(m_pSetEnvAttr))(a,b,c,d)
111 : : #define NSQLDataSources(a,b,c,d,e,f,g,h) (*(TSQLDataSources)(m_pDataSources))(a,b,c,d,e,f,g,h)
112 : : #endif
113 : :
114 : : //=========================================================================
115 : : //= OOdbcLibWrapper
116 : : //=========================================================================
117 : : DBG_NAME(OOdbcLibWrapper)
118 : : //-------------------------------------------------------------------------
119 : : #ifdef HAVE_ODBC_SUPPORT
120 : 0 : OOdbcLibWrapper::OOdbcLibWrapper()
121 : 0 : :m_pOdbcLib(NULL)
122 : : {
123 : : DBG_CTOR(OOdbcLibWrapper,NULL);
124 : :
125 : 0 : }
126 : : #endif
127 : :
128 : : //-------------------------------------------------------------------------
129 : 0 : sal_Bool OOdbcLibWrapper::load(const sal_Char* _pLibPath)
130 : : {
131 : 0 : m_sLibPath = ::rtl::OUString::createFromAscii(_pLibPath);
132 : : #ifdef HAVE_ODBC_SUPPORT
133 : : // load the module
134 : 0 : m_pOdbcLib = osl_loadModule(m_sLibPath.pData, SAL_LOADMODULE_NOW);
135 : 0 : return (NULL != m_pOdbcLib);
136 : : #endif
137 : : }
138 : :
139 : : //-------------------------------------------------------------------------
140 : 0 : void OOdbcLibWrapper::unload()
141 : : {
142 : : #ifdef HAVE_ODBC_SUPPORT
143 [ # # ]: 0 : if (isLoaded())
144 : : {
145 : 0 : osl_unloadModule(m_pOdbcLib);
146 : 0 : m_pOdbcLib = NULL;
147 : : }
148 : : #endif
149 : 0 : }
150 : :
151 : : //-------------------------------------------------------------------------
152 : 0 : oslGenericFunction OOdbcLibWrapper::loadSymbol(const sal_Char* _pFunctionName)
153 : : {
154 [ # # ]: 0 : return osl_getFunctionSymbol(m_pOdbcLib, ::rtl::OUString::createFromAscii(_pFunctionName).pData);
155 : : }
156 : :
157 : : //-------------------------------------------------------------------------
158 : 0 : OOdbcLibWrapper::~OOdbcLibWrapper()
159 : : {
160 [ # # ]: 0 : unload();
161 : :
162 : : DBG_DTOR(OOdbcLibWrapper,NULL);
163 : 0 : }
164 : :
165 : : //=========================================================================
166 : : //= OOdbcEnumeration
167 : : //=========================================================================
168 : : struct OdbcTypesImpl
169 : : {
170 : : #ifdef HAVE_ODBC_SUPPORT
171 : : SQLHANDLE hEnvironment;
172 : 0 : OdbcTypesImpl() : hEnvironment(0) { }
173 : : #else
174 : : void* pDummy;
175 : : #endif
176 : : };
177 : : DBG_NAME(OOdbcEnumeration)
178 : : //-------------------------------------------------------------------------
179 : 0 : OOdbcEnumeration::OOdbcEnumeration()
180 : : #ifdef HAVE_ODBC_SUPPORT
181 : : :m_pAllocHandle(NULL)
182 : : ,m_pSetEnvAttr(NULL)
183 : : ,m_pDataSources(NULL)
184 [ # # ]: 0 : ,m_pImpl(new OdbcTypesImpl)
185 : : #endif
186 : : {
187 : : DBG_CTOR(OOdbcEnumeration,NULL);
188 : :
189 [ # # ]: 0 : sal_Bool bLoaded = load(ODBC_LIBRARY);
190 : : #ifdef ODBC_LIBRARY_1
191 [ # # ]: 0 : if ( !bLoaded )
192 [ # # ]: 0 : bLoaded = load(ODBC_LIBRARY_1);
193 : : #endif
194 : :
195 [ # # ]: 0 : if ( bLoaded )
196 : : {
197 : : #ifdef HAVE_ODBC_SUPPORT
198 : : // load the generic functions
199 [ # # ]: 0 : m_pAllocHandle = loadSymbol("SQLAllocHandle");
200 [ # # ]: 0 : m_pFreeHandle = loadSymbol("SQLFreeHandle");
201 [ # # ]: 0 : m_pSetEnvAttr = loadSymbol("SQLSetEnvAttr");
202 [ # # ]: 0 : m_pDataSources = loadSymbol("SQLDataSources");
203 : :
204 : : // all or nothing
205 [ # # ][ # # ]: 0 : if (!m_pAllocHandle || !m_pSetEnvAttr || !m_pDataSources || !m_pFreeHandle)
[ # # ][ # # ]
206 : : {
207 [ # # ]: 0 : unload();
208 : 0 : m_pAllocHandle = m_pFreeHandle = m_pSetEnvAttr = m_pDataSources = NULL;
209 : : }
210 : : #endif
211 : : }
212 : 0 : }
213 : :
214 : : //-------------------------------------------------------------------------
215 : 0 : OOdbcEnumeration::~OOdbcEnumeration()
216 : : {
217 [ # # ]: 0 : freeEnv();
218 : 0 : delete m_pImpl;
219 : :
220 : : DBG_DTOR(OOdbcEnumeration,NULL);
221 : 0 : }
222 : :
223 : : //-------------------------------------------------------------------------
224 : 0 : sal_Bool OOdbcEnumeration::allocEnv()
225 : : {
226 : : OSL_ENSURE(isLoaded(), "OOdbcEnumeration::allocEnv: not loaded!");
227 [ # # ]: 0 : if (!isLoaded())
228 : 0 : return sal_False;
229 : :
230 : : #ifdef HAVE_ODBC_SUPPORT
231 [ # # ]: 0 : if (m_pImpl->hEnvironment)
232 : : // nothing to do
233 : 0 : return sal_True;
234 : 0 : SQLRETURN nResult = NSQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &m_pImpl->hEnvironment);
235 [ # # ]: 0 : if (SQL_SUCCESS != nResult)
236 : : // can't do anything without environment
237 : 0 : return sal_False;
238 : :
239 : 0 : NSQLSetEnvAttr(m_pImpl->hEnvironment, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER);
240 : 0 : return sal_True;
241 : : #else
242 : : return sal_False;
243 : : #endif
244 : : }
245 : :
246 : : //-------------------------------------------------------------------------
247 : 0 : void OOdbcEnumeration::freeEnv()
248 : : {
249 : : #ifdef HAVE_ODBC_SUPPORT
250 [ # # ]: 0 : if (m_pImpl->hEnvironment)
251 : 0 : NSQLFreeHandle(SQL_HANDLE_ENV, m_pImpl->hEnvironment);
252 : 0 : m_pImpl->hEnvironment = 0;
253 : : #endif
254 : 0 : }
255 : :
256 : : //-------------------------------------------------------------------------
257 : 0 : void OOdbcEnumeration::getDatasourceNames(StringBag& _rNames)
258 : : {
259 : : OSL_ENSURE(isLoaded(), "OOdbcEnumeration::getDatasourceNames: not loaded!");
260 [ # # ]: 0 : if (!isLoaded())
261 : : return;
262 : :
263 [ # # ][ # # ]: 0 : if (!allocEnv())
264 : : {
265 : : OSL_FAIL("OOdbcEnumeration::getDatasourceNames: could not allocate an ODBC environment!");
266 : : return;
267 : : }
268 : :
269 : : #ifdef HAVE_ODBC_SUPPORT
270 : : // now that we have an environment collect the data source names
271 : : UCHAR szDSN[SQL_MAX_DSN_LENGTH+1];
272 : : SWORD pcbDSN;
273 : : UCHAR szDescription[1024+1];
274 : : SWORD pcbDescription;
275 : 0 : SQLRETURN nResult = SQL_SUCCESS;
276 [ # # ]: 0 : rtl_TextEncoding nTextEncoding = osl_getThreadTextEncoding();
277 : :
278 [ # # ][ # # ]: 0 : for ( nResult = NSQLDataSources(m_pImpl->hEnvironment, SQL_FETCH_FIRST, szDSN, sizeof(szDSN), &pcbDSN, szDescription, sizeof(szDescription)-1, &pcbDescription);
279 : : ;
280 : 0 : nResult = NSQLDataSources(m_pImpl->hEnvironment, SQL_FETCH_NEXT, szDSN, sizeof(szDSN), &pcbDSN, szDescription, sizeof(szDescription)-1, &pcbDescription)
281 : : )
282 : : {
283 [ # # ]: 0 : if (nResult != SQL_SUCCESS)
284 : : // no further error handling
285 : 0 : break;
286 : : else
287 : : {
288 [ # # ]: 0 : ::rtl::OUString aCurrentDsn(reinterpret_cast<const char*>(szDSN),pcbDSN, nTextEncoding);
289 [ # # ]: 0 : _rNames.insert(aCurrentDsn);
290 : : }
291 : : }
292 : : #endif
293 : : }
294 : :
295 : : #ifdef HAVE_ODBC_ADMINISTRATION
296 : :
297 : : //=========================================================================
298 : : //= ProcessTerminationWait
299 : : //=========================================================================
300 : : class ProcessTerminationWait : public ::osl::Thread
301 : : {
302 : : oslProcess m_hProcessHandle;
303 : : Link m_aFinishHdl;
304 : :
305 : : public:
306 : : ProcessTerminationWait( oslProcess _hProcessHandle, const Link& _rFinishHdl )
307 : : :m_hProcessHandle( _hProcessHandle )
308 : : ,m_aFinishHdl( _rFinishHdl )
309 : : {
310 : : }
311 : :
312 : : protected:
313 : : virtual void SAL_CALL run()
314 : : {
315 : : osl_joinProcess( m_hProcessHandle );
316 : : osl_freeProcessHandle( m_hProcessHandle );
317 : : Application::PostUserEvent( m_aFinishHdl );
318 : : }
319 : : };
320 : :
321 : : //=========================================================================
322 : : //= OOdbcManagement
323 : : //=========================================================================
324 : : //-------------------------------------------------------------------------
325 : : OOdbcManagement::OOdbcManagement( const Link& _rAsyncFinishCallback )
326 : : :m_pProcessWait( NULL )
327 : : ,m_aAsyncFinishCallback( _rAsyncFinishCallback )
328 : : {
329 : : }
330 : :
331 : : //-------------------------------------------------------------------------
332 : : OOdbcManagement::~OOdbcManagement()
333 : : {
334 : : // wait for our thread to be finished
335 : : if ( m_pProcessWait.get() )
336 : : m_pProcessWait->join();
337 : : }
338 : :
339 : : //-------------------------------------------------------------------------
340 : : bool OOdbcManagement::manageDataSources_async()
341 : : {
342 : : OSL_PRECOND( !isRunning(), "OOdbcManagement::manageDataSources_async: still running from the previous call!" );
343 : : if ( isRunning() )
344 : : return false;
345 : :
346 : : // this is done in an external process, due to #i78733#
347 : : // (and note this whole functionality is supported on Windows only, ATM)
348 : : ::rtl::OUString sExecutableName( RTL_CONSTASCII_USTRINGPARAM( "$BRAND_BASE_DIR/program/odbcconfig.exe" ) );
349 : : ::rtl::Bootstrap::expandMacros( sExecutableName ); //TODO: detect failure
350 : : oslProcess hProcessHandle(0);
351 : : oslProcessError eError = osl_executeProcess( sExecutableName.pData, NULL, 0, 0, NULL, NULL, NULL, 0, &hProcessHandle );
352 : : if ( eError != osl_Process_E_None )
353 : : return false;
354 : :
355 : : m_pProcessWait.reset( new ProcessTerminationWait( hProcessHandle, m_aAsyncFinishCallback ) );
356 : : m_pProcessWait->create();
357 : : return true;
358 : : }
359 : :
360 : : //-------------------------------------------------------------------------
361 : : bool OOdbcManagement::isRunning() const
362 : : {
363 : : return ( m_pProcessWait.get() && m_pProcessWait->isRunning() );
364 : : }
365 : :
366 : : #endif // HAVE_ODBC_ADMINISTRATION
367 : :
368 : : //.........................................................................
369 : : } // namespace dbaui
370 : : //.........................................................................
371 : :
372 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|