diff --git a/pw3270.cbp b/pw3270.cbp index 9e9b764..44b573a 100644 --- a/pw3270.cbp +++ b/pw3270.cbp @@ -76,6 +76,10 @@ + + diff --git a/src/classlib/class.mak.in b/src/classlib/class.mak.in index c51dc97..3fa88d6 100644 --- a/src/classlib/class.mak.in +++ b/src/classlib/class.mak.in @@ -27,7 +27,7 @@ CLASS_CFLAGS=@CFLAGS@ @DLL_CFLAGS@ @DBUS_CFLAGS@ CLASS_LIBS=@LIBICONV@ @DBUS_LIBS@ -CLASS_SRC=session.cc exception.cc local.cc remote.cc +CLASS_SRC=session.cc exception.cc local.cc remote.cc module.cc CLASS_DEBUG_OBJECTS=$(foreach SRC, $(basename $(CLASS_SRC)), $(OBJDBG)/classlib/$(SRC)@OBJEXT@) CLASS_RELEASE_OBJECTS=$(foreach SRC, $(basename $(CLASS_SRC)), $(OBJRLS)/classlib/$(SRC)@OBJEXT@) diff --git a/src/classlib/local.cc b/src/classlib/local.cc index 5e76c2b..b1e1303 100644 --- a/src/classlib/local.cc +++ b/src/classlib/local.cc @@ -114,166 +114,11 @@ namespace PW3270_NAMESPACE { - class local : public session + class local : public session, private module { private: - H3270 * hSession; - - #ifdef WIN32 - - HMODULE hModule; - - int get_datadir(LPSTR datadir) - { - HKEY hKey = 0; - unsigned long datalen = strlen(datadir); - - *datadir = 0; - - if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Software\\pw3270",0,KEY_QUERY_VALUE,&hKey) == ERROR_SUCCESS) - { - unsigned long datatype; // #defined in winnt.h (predefined types 0-11) - if(RegQueryValueExA(hKey,"datadir",NULL,&datatype,(LPBYTE) datadir,&datalen) != ERROR_SUCCESS) - *datadir = 0; - RegCloseKey(hKey); - } - - return *datadir; - } - #else - - void * hModule; - - #endif // WIN32 - - /** - * Dynamically load lib3270 - * - * @return 0 if the library was loaded, -1 on error. - * - */ - int load3270(void) - { - #ifdef WIN32 - static const char *dllname = "lib3270.dll." PACKAGE_VERSION; - - HMODULE kernel; - HANDLE cookie = NULL; - DWORD rc; - HANDLE WINAPI (*AddDllDirectory)(PCWSTR NewDirectory); - BOOL WINAPI (*RemoveDllDirectory)(HANDLE Cookie); - UINT errorMode; - char datadir[4096]; - char buffer[4096]; - - kernel = LoadLibrary("kernel32.dll"); - AddDllDirectory = (HANDLE WINAPI (*)(PCWSTR)) GetProcAddress(kernel,"AddDllDirectory"); - RemoveDllDirectory = (BOOL WINAPI (*)(HANDLE)) GetProcAddress(kernel,"RemoveDllDirectory"); - - // Notify user in case of error loading protocol DLL - // http://msdn.microsoft.com/en-us/library/windows/desktop/ms680621(v=vs.85).aspx - errorMode = SetErrorMode(1); - - memset(datadir,' ',4095); - datadir[4095] = 0; - - if(get_datadir(datadir)) - { - trace("Datadir=[%s] AddDllDirectory=%p RemoveDllDirectory=%p\n",datadir,AddDllDirectory,RemoveDllDirectory); - - if(AddDllDirectory) - { - wchar_t *path = (wchar_t *) malloc(4096*sizeof(wchar_t)); - mbstowcs(path, datadir, 4095); - cookie = AddDllDirectory(path); - free(path); - } - - #ifdef DEBUG - snprintf(buffer,4096,"%s\\.bin\\Debug\\%s",datadir,dllname); - #else - snprintf(buffer,4096,"%s\\%s",datadir,dllname); - #endif // DEBUG - - trace("Loading [%s] [%s]",buffer,datadir); - hModule = LoadLibrary(buffer); - - trace("Module=%p rc=%d",hModule,(int) GetLastError()); - - if(hModule == NULL) - { - // Enable DLL error popup and try again with full path - SetErrorMode(0); - hModule = LoadLibraryEx(buffer,NULL,LOAD_LIBRARY_SEARCH_DEFAULT_DIRS|LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR); - } - - rc = GetLastError(); - - trace("%s hModule=%p rc=%d",buffer,hModule,(int) rc); - } - else - { - hModule = LoadLibrary(dllname); - rc = GetLastError(); - } - - SetErrorMode(errorMode); - - trace("%s hModule=%p rc=%d",dllname,hModule,(int) rc); - - if(cookie && RemoveDllDirectory) - RemoveDllDirectory(cookie); - - if(kernel) - FreeLibrary(kernel); - - if(hModule) - return 0; - - throw exception("Can't load %s",dllname); - - #else - dlerror(); - - hModule = dlopen("lib3270.so." PACKAGE_VERSION, RTLD_NOW); - if(hModule) - return 0; - - throw exception("Can't load lib3270: %s",dlerror()); - - #endif // WIN32 - - return -1; - - } - - void * get_symbol(const char *name) - { -#ifdef WIN32 - void *symbol = (void *) GetProcAddress(hModule,name); - - if(symbol) - return symbol; - - throw exception("Can't load symbol lib3270::%s",name); - -#else - void *symbol; - - symbol = dlsym(hModule,name); - - if(symbol) - return symbol; - - throw exception("Can't load symbol lib3270::%s dlerror was \"%s\"",name,dlerror()); - -#endif // WIN32 - - return NULL; - - } - + H3270 * hSession; // Lib3270 entry points const char * (*_get_version)(void); @@ -313,7 +158,7 @@ public: - local() + local() throw(std::exception) : module("lib3270",PACKAGE_VERSION) { H3270 * (*lib3270_new)(const char *); void (*set_log_handler)(void (*loghandler)(H3270 *, const char *, int, const char *, va_list)); @@ -367,17 +212,11 @@ }; - - if(load3270()) - return; - - trace("hModule=%p",hModule); - for(unsigned int f = 0; f < (sizeof (call) / sizeof ((call)[0]));f++) { *call[f].entry = (void *) get_symbol(call[f].name); if(!*call[f].entry) - return; + throw exception("Can't find symbol %s",call[f].name); } // Get Session handle, setup base callbacks @@ -400,12 +239,6 @@ } catch(exception e) { } - #ifdef WIN32 - FreeLibrary(hModule); - #else - dlclose(hModule); - #endif // WIN32 - } bool is_connected(void) @@ -599,7 +432,7 @@ }; - session * session::create_local(void) + session * session::create_local(void) throw (std::exception) { return new local(); } diff --git a/src/classlib/module.cc b/src/classlib/module.cc new file mode 100644 index 0000000..cc919a6 --- /dev/null +++ b/src/classlib/module.cc @@ -0,0 +1,215 @@ +/* + * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270 + * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a + * aplicativos mainframe. Registro no INPI sob o nome G3270. + * + * Copyright (C) <2008> + * + * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob + * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela + * Free Software Foundation. + * + * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER + * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO + * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para + * obter mais detalhes. + * + * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este + * programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin + * St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Este programa está nomeado como module.cc e possui - linhas de código. + * + * Contatos: + * + * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck) + * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça) + * + */ + +#if defined WIN32 + + // http://msdn.microsoft.com/en-us/library/windows/desktop/ms684179(v=vs.85).aspx + #ifndef LOAD_LIBRARY_SEARCH_DEFAULT_DIRS + #define LOAD_LIBRARY_SEARCH_DEFAULT_DIRS 0x00001000 + #endif // LOAD_LIBRARY_SEARCH_DEFAULT_DIRS + + #ifndef LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR + #define LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR 0x00000100 + #endif // LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR + + #include + +#else + + #include + +#endif + +#include + +/*---[ Implement ]----------------------------------------------------------------------------------*/ + + +namespace PW3270_NAMESPACE +{ + +#ifdef WIN32 + int module::get_datadir(LPSTR datadir) + { + HKEY hKey = 0; + unsigned long datalen = strlen(datadir); + + *datadir = 0; + + if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Software\\pw3270",0,KEY_QUERY_VALUE,&hKey) == ERROR_SUCCESS) + { + unsigned long datatype; // #defined in winnt.h (predefined types 0-11) + if(RegQueryValueExA(hKey,"datadir",NULL,&datatype,(LPBYTE) datadir,&datalen) != ERROR_SUCCESS) + *datadir = 0; + RegCloseKey(hKey); + } + + return *datadir; + } +#endif // WIN32 + + module::module(const char *name, const char *version) throw (std::exception) + { + string dllname = name; + +#ifdef WIN32 + + dllname += ".dll"; + if(version) + { + dllname += "."; + dllname += version; + } + + HMODULE kernel; + HANDLE cookie = NULL; + DWORD rc; + HANDLE WINAPI (*AddDllDirectory)(PCWSTR NewDirectory); + BOOL WINAPI (*RemoveDllDirectory)(HANDLE Cookie); + UINT errorMode; + char datadir[4096]; + char buffer[4096]; + + kernel = LoadLibrary("kernel32.dll"); + AddDllDirectory = (HANDLE WINAPI (*)(PCWSTR)) GetProcAddress(kernel,"AddDllDirectory"); + RemoveDllDirectory = (BOOL WINAPI (*)(HANDLE)) GetProcAddress(kernel,"RemoveDllDirectory"); + + // Notify user in case of error loading protocol DLL + // http://msdn.microsoft.com/en-us/library/windows/desktop/ms680621(v=vs.85).aspx + errorMode = SetErrorMode(1); + + memset(datadir,' ',4095); + datadir[4095] = 0; + + if(get_datadir(datadir)) + { + trace("Datadir=[%s] AddDllDirectory=%p RemoveDllDirectory=%p\n",datadir,AddDllDirectory,RemoveDllDirectory); + + if(AddDllDirectory) + { + wchar_t *path = (wchar_t *) malloc(4096*sizeof(wchar_t)); + mbstowcs(path, datadir, 4095); + cookie = AddDllDirectory(path); + free(path); + } + +#ifdef DEBUG + snprintf(buffer,4096,"%s\\.bin\\Debug\\%s",datadir,dllname.c_str()); +#else + snprintf(buffer,4096,"%s\\%s",datadir,dllname.c_str()); +#endif // DEBUG + + trace("Loading [%s] [%s]",buffer,datadir); + hModule = LoadLibrary(buffer); + + trace("Module=%p rc=%d",hModule,(int) GetLastError()); + + if(hModule == NULL) + { + // Enable DLL error popup and try again with full path + SetErrorMode(0); + hModule = LoadLibraryEx(buffer,NULL,LOAD_LIBRARY_SEARCH_DEFAULT_DIRS|LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR); + } + + rc = GetLastError(); + + trace("%s hModule=%p rc=%d",buffer,hModule,(int) rc); + } + else + { + hModule = LoadLibrary(dllname); + rc = GetLastError(); + } + + SetErrorMode(errorMode); + + trace("%s hModule=%p rc=%d",dllname,hModule,(int) rc); + + if(cookie && RemoveDllDirectory) + RemoveDllDirectory(cookie); + + if(kernel) + FreeLibrary(kernel); + + if(!hModule) + throw exception("Can't load %s",dllname.c_str()); + +#else + dllname += ".so"; + if(version) + { + dllname += "."; + dllname += version; + } + + dlerror(); + + hModule = dlopen(dllname.c_str(), RTLD_NOW); + if(!hModule) + throw exception("Can't load lib3270: %s",dllname.c_str()); + +#endif // WIN32 + + + } + + module::~module() + { +#ifdef WIN32 + FreeLibrary(hModule); +#else + dlclose(hModule); +#endif // WIN32 + } + + + void * module::get_symbol(const char *name) + { + void *symbol; + +#ifdef WIN32 + + symbol = (void *) GetProcAddress(hModule,name); + + if(!symbol) + throw exception("Can't load symbol %s",name); + +#else + symbol = dlsym(hModule,name); + + if(!symbol) + throw exception("Can't load symbol %s dlerror was \"%s\"",name,dlerror()); + +#endif // WIN32 + + return symbol; + } + +} + diff --git a/src/classlib/remote.cc b/src/classlib/remote.cc index 9b3d12b..598dda2 100644 --- a/src/classlib/remote.cc +++ b/src/classlib/remote.cc @@ -398,7 +398,7 @@ } #endif // HAVE_DBUS - remote(const char *session) + remote(const char *session) throw (std::exception) { #if defined(WIN32) static DWORD dwMode = PIPE_READMODE_MESSAGE; @@ -499,27 +499,6 @@ Sleep(10); } } - /* - WIN32_FIND_DATA FindFileData; - - timer = time(0)+20; - while(hPipe == INVALID_HANDLE_VALUE && time(0) < timer) - { - hPipe = FindFirstFile(buffer, &FindFileData); - Sleep(10); - } - - if(hPipe != INVALID_HANDLE_VALUE) - { - CloseHandle(hPipe); - hPipe = CreateFile(buffer,GENERIC_WRITE|GENERIC_READ,0,NULL,OPEN_EXISTING,0,NULL); - } - else - { - throw exception(GetLastError(),"Timeout waiting for %s instance",PACKAGE_NAME); - return; - } - */ if(hPipe == INVALID_HANDLE_VALUE) { @@ -1377,7 +1356,7 @@ }; - session * session::create_remote(const char *session) + session * session::create_remote(const char *session) throw (std::exception) { return new remote(session); } diff --git a/src/classlib/session.cc b/src/classlib/session.cc index 542483e..0e2872d 100644 --- a/src/classlib/session.cc +++ b/src/classlib/session.cc @@ -96,7 +96,7 @@ } // Factory methods and settings - session * session::create(const char *name) + session * session::create(const char *name) throw (std::exception) { if(factory) return factory(name); diff --git a/src/include/pw3270/class.h b/src/include/pw3270/class.h index 8c2d906..97af0d4 100644 --- a/src/include/pw3270/class.h +++ b/src/include/pw3270/class.h @@ -89,6 +89,32 @@ }; +#if defined (HAVE_GNUC_VISIBILITY) + class __attribute__((visibility("default"))) module +#elif defined(WIN32) + class __declspec (dllexport) module +#else + class module +#endif + { + private: +#ifdef WIN32 + HMODULE hModule; + int get_datadir(LPSTR datadir); +#else + void * hModule; + +#endif // WIN32 + + public: + module(const char *name, const char *version = NULL) throw (std::exception); + ~module(); + + void * get_symbol(const char *name); + + }; + + #if defined (HAVE_GNUC_VISIBILITY) class __attribute__((visibility("default"))) session @@ -104,7 +130,7 @@ // Factory methods and settings static session * start(const char *name = 0); - static session * create(const char *name = 0); + static session * create(const char *name = 0) throw (std::exception); static session * get_default(void); static void set_plugin(session * (*factory)(const char *name)); @@ -221,8 +247,8 @@ static session * (*factory)(const char *name); - static session * create_remote(const char *name); - static session * create_local(void); + static session * create_remote(const char *name) throw (std::exception); + static session * create_local(void) throw (std::exception); #ifdef HAVE_ICONV iconv_t conv2Local; -- libgit2 0.21.2