tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / dbaccess / source / ui / dlg / odbcconfig.cxx
blobb2f3a45ff90d0dc4b72b2918a5f2d351adc8595e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <config_folders.h>
21 #include "odbcconfig.hxx"
23 #include <rtl/bootstrap.hxx>
24 #include <rtl/ustring.hxx>
25 #include <osl/diagnose.h>
26 #include <osl/process.h>
27 #include <osl/thread.hxx>
28 #include <vcl/svapp.hxx>
30 #ifdef HAVE_ODBC_SUPPORT
32 #if defined(_WIN32)
33 #define ODBC_LIBRARY "ODBC32.DLL"
34 #endif
35 #ifdef UNX
36 #ifdef MACOSX
37 #define ODBC_LIBRARY "libiodbc.dylib"
38 #else
39 #define ODBC_LIBRARY_PLAIN "libodbc.so"
40 #define ODBC_LIBRARY_1 "libodbc.so.1"
41 #define ODBC_LIBRARY "libodbc.so.2"
42 #endif
43 #endif
45 #include <connectivity/odbc.hxx>
47 #else
49 #define ODBC_LIBRARY ""
51 #endif // HAVE_ODBC_SUPPORT
53 namespace dbaui
56 #ifdef HAVE_ODBC_SUPPORT
57 typedef SQLRETURN (SQL_API* TSQLManageDataSource) (SQLHWND hwndParent);
58 typedef SQLRETURN (SQL_API* TSQLAllocHandle) (SQLSMALLINT HandleType, SQLHANDLE InputHandle, SQLHANDLE* OutputHandlePtr);
59 typedef SQLRETURN (SQL_API* TSQLFreeHandle) (SQLSMALLINT HandleType, SQLHANDLE Handle);
60 typedef SQLRETURN (SQL_API* TSQLSetEnvAttr) (SQLHENV EnvironmentHandle, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER StringLength);
61 typedef SQLRETURN (SQL_API* TSQLDataSources) (SQLHENV EnvironmentHandle, SQLUSMALLINT Direction, SQLCHAR* ServerName,
62 SQLSMALLINT BufferLength1, SQLSMALLINT* NameLength1Ptr, SQLCHAR* Description, SQLSMALLINT BufferLength2, SQLSMALLINT* NameLength2Ptr);
64 #endif
66 // OOdbcLibWrapper
68 bool OOdbcEnumeration::load(const char* _pLibPath)
70 m_sLibPath = OUString::createFromAscii(_pLibPath);
71 #if defined(HAVE_ODBC_SUPPORT) && !defined(DISABLE_DYNLOADING)
72 // load the module
73 m_pOdbcLib = osl_loadModule(m_sLibPath.pData, SAL_LOADMODULE_NOW);
74 return (nullptr != m_pOdbcLib);
75 #else
76 return sal_False;
77 #endif
80 void OOdbcEnumeration::unload()
82 #if defined(HAVE_ODBC_SUPPORT) && !defined(DISABLE_DYNLOADING)
83 if (isLoaded())
85 osl_unloadModule(m_pOdbcLib);
86 m_pOdbcLib = nullptr;
88 #endif
91 oslGenericFunction OOdbcEnumeration::loadSymbol(const char* _pFunctionName)
93 return osl_getFunctionSymbol(m_pOdbcLib, OUString::createFromAscii(_pFunctionName).pData);
97 struct OdbcTypesImpl
99 #ifdef HAVE_ODBC_SUPPORT
100 SQLHANDLE hEnvironment;
101 OdbcTypesImpl() : hEnvironment(nullptr) { }
102 #else
103 void* pDummy;
104 #endif
107 OOdbcEnumeration::OOdbcEnumeration()
108 :m_pOdbcLib(nullptr)
109 #ifdef HAVE_ODBC_SUPPORT
110 ,m_pAllocHandle(nullptr)
111 ,m_pFreeHandle(nullptr)
112 ,m_pSetEnvAttr(nullptr)
113 ,m_pDataSources(nullptr)
114 ,m_pImpl(new OdbcTypesImpl)
115 #endif
117 bool bLoaded = load(ODBC_LIBRARY);
118 #ifdef ODBC_LIBRARY_1
119 if ( !bLoaded )
120 bLoaded = load(ODBC_LIBRARY_1);
121 #endif
122 #ifdef ODBC_LIBRARY_PLAIN
123 if ( !bLoaded )
124 bLoaded = load(ODBC_LIBRARY_PLAIN);
125 #endif
127 if ( !bLoaded )
128 return;
130 #ifdef HAVE_ODBC_SUPPORT
131 // load the generic functions
132 m_pAllocHandle = loadSymbol("SQLAllocHandle");
133 m_pFreeHandle = loadSymbol("SQLFreeHandle");
134 m_pSetEnvAttr = loadSymbol("SQLSetEnvAttr");
135 m_pDataSources = loadSymbol("SQLDataSources");
137 // all or nothing
138 if (!m_pAllocHandle || !m_pSetEnvAttr || !m_pDataSources || !m_pFreeHandle)
140 unload();
141 m_pAllocHandle = m_pFreeHandle = m_pSetEnvAttr = m_pDataSources = nullptr;
143 #endif
146 OOdbcEnumeration::~OOdbcEnumeration()
148 freeEnv();
149 unload();
152 // OOdbcEnumeration
153 bool OOdbcEnumeration::allocEnv()
155 OSL_ENSURE(isLoaded(), "OOdbcEnumeration::allocEnv: not loaded!");
156 if (!isLoaded())
157 return false;
159 #ifdef HAVE_ODBC_SUPPORT
160 if (m_pImpl->hEnvironment)
161 // nothing to do
162 return true;
163 SQLRETURN nResult = (*reinterpret_cast<TSQLAllocHandle>(m_pAllocHandle))(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &m_pImpl->hEnvironment);
164 if (SQL_SUCCESS != nResult)
165 // can't do anything without environment
166 return false;
168 (*reinterpret_cast<TSQLSetEnvAttr>(m_pSetEnvAttr))(m_pImpl->hEnvironment, SQL_ATTR_ODBC_VERSION, reinterpret_cast<SQLPOINTER>(SQL_OV_ODBC3),SQL_IS_INTEGER);
169 return true;
170 #else
171 return sal_False;
172 #endif
175 void OOdbcEnumeration::freeEnv()
177 #ifdef HAVE_ODBC_SUPPORT
178 if (m_pImpl->hEnvironment)
179 (*reinterpret_cast<TSQLFreeHandle>(m_pFreeHandle))(SQL_HANDLE_ENV, m_pImpl->hEnvironment);
180 m_pImpl->hEnvironment = nullptr;
181 #endif
184 void OOdbcEnumeration::getDatasourceNames(std::set<OUString>& _rNames)
186 OSL_ENSURE(isLoaded(), "OOdbcEnumeration::getDatasourceNames: not loaded!");
187 if (!isLoaded())
188 return;
190 if (!allocEnv())
192 OSL_FAIL("OOdbcEnumeration::getDatasourceNames: could not allocate an ODBC environment!");
193 return;
196 #ifdef HAVE_ODBC_SUPPORT
197 // now that we have an environment collect the data source names
198 UCHAR szDSN[SQL_MAX_DSN_LENGTH+1];
199 SWORD pcbDSN;
200 UCHAR szDescription[1024+1];
201 SWORD pcbDescription;
202 SQLRETURN nResult = SQL_SUCCESS;
203 rtl_TextEncoding nTextEncoding = osl_getThreadTextEncoding();
205 for ( nResult = (*reinterpret_cast<TSQLDataSources>(m_pDataSources))(m_pImpl->hEnvironment, SQL_FETCH_FIRST, szDSN,
206 sizeof(szDSN), &pcbDSN, szDescription, sizeof(szDescription)-1, &pcbDescription);
208 nResult = (*reinterpret_cast<TSQLDataSources>(m_pDataSources))(m_pImpl->hEnvironment, SQL_FETCH_NEXT, szDSN,
209 sizeof(szDSN), &pcbDSN, szDescription, sizeof(szDescription)-1, &pcbDescription)
212 if (nResult != SQL_SUCCESS)
213 // no further error handling
214 break;
215 else
217 OUString aCurrentDsn(reinterpret_cast<const char*>(szDSN),pcbDSN, nTextEncoding);
218 _rNames.insert(aCurrentDsn);
221 #else
222 (void) _rNames;
223 #endif
226 #ifdef HAVE_ODBC_ADMINISTRATION
228 // ProcessTerminationWait
229 class ProcessTerminationWait : public ::osl::Thread
231 oslProcess m_hProcessHandle;
232 Link<void*,void> m_aFinishHdl;
233 ImplSVEvent* m_nEventId;
235 public:
236 ProcessTerminationWait( oslProcess _hProcessHandle, const Link<void*,void>& _rFinishHdl )
237 : m_hProcessHandle( _hProcessHandle )
238 , m_aFinishHdl( _rFinishHdl )
239 , m_nEventId(nullptr)
243 void disableCallback()
245 // if finished event not posted yet, disable by turning it to a no-op Link
246 m_aFinishHdl = Link<void*, void>();
247 if (m_nEventId)
249 // already posted, remove it
250 Application::RemoveUserEvent(m_nEventId);
251 m_nEventId = nullptr;
255 void receivedCallback()
257 m_nEventId = nullptr;
260 protected:
261 virtual void SAL_CALL run() override
263 osl_setThreadName("dbaui::ProcessTerminationWait");
265 osl_joinProcess( m_hProcessHandle );
266 osl_freeProcessHandle( m_hProcessHandle );
267 m_nEventId = Application::PostUserEvent( m_aFinishHdl );
271 // OOdbcManagement
272 OOdbcManagement::OOdbcManagement(const Link<void*,void>& rAsyncFinishCallback)
273 : m_aAsyncFinishCallback(rAsyncFinishCallback)
277 OOdbcManagement::~OOdbcManagement()
279 // wait for our thread to be finished
280 if ( m_pProcessWait )
281 m_pProcessWait->join();
284 bool OOdbcManagement::manageDataSources_async()
286 OSL_PRECOND( !isRunning(), "OOdbcManagement::manageDataSources_async: still running from the previous call!" );
287 if ( isRunning() )
288 return false;
290 // this is done in an external process, due to #i78733#
291 // (and note this whole functionality is supported on Windows only, ATM)
292 OUString sExecutableName( "$BRAND_BASE_DIR/" LIBO_LIBEXEC_FOLDER "/odbcconfig.exe" );
293 ::rtl::Bootstrap::expandMacros( sExecutableName ); //TODO: detect failure
294 oslProcess hProcessHandle(nullptr);
295 oslProcessError eError = osl_executeProcess( sExecutableName.pData, nullptr, 0, 0, nullptr, nullptr, nullptr, 0, &hProcessHandle );
296 if ( eError != osl_Process_E_None )
297 return false;
299 m_pProcessWait.reset( new ProcessTerminationWait( hProcessHandle, m_aAsyncFinishCallback ) );
300 m_pProcessWait->create();
301 return true;
304 void OOdbcManagement::disableCallback()
306 if (m_pProcessWait)
307 m_pProcessWait->disableCallback();
310 void OOdbcManagement::receivedCallback()
312 if (m_pProcessWait)
313 m_pProcessWait->receivedCallback();
316 bool OOdbcManagement::isRunning() const
318 return ( m_pProcessWait && m_pProcessWait->isRunning() );
321 #endif // HAVE_ODBC_ADMINISTRATION
323 } // namespace dbaui
325 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */