Commit 249d46fd03bd3337aaa27334041a110ab58294ad

Authored by Perry Werneck
1 parent ccd4292a
Exists in master

Adding methods for windows delayed loading.

configure.ac
... ... @@ -101,7 +101,7 @@ case "$host" in
101 101 CFLAGS="$CFLAGS -pthread -D_WIN32_WINNT=0x0600"
102 102 CXXFLAGS="$CXXFLAGS -pthread -D_WIN32_WINNT=0x0600"
103 103 LIBS="$LIBS -lws2_32 -lwtsapi32 -lcomdlg32"
104   - LDFLAGS="$LDFLAGS -static-libgcc -static-libstdc++ -Wl,-Bstatic,--whole-archive -lwinpthread -Wl,--no-whole-archive,-Bdynamic"
  104 + LDFLAGS="$LDFLAGS -static-libgcc -static-libstdc++"
105 105 DLLEXT=".dll"
106 106  
107 107 app_win32_revision=$(date +%-y.%-m.%-d.%-H)
... ... @@ -184,6 +184,7 @@ AC_ARG_WITH([static-ipc3270],
184 184 if test "$app_cv_static_ipc3270" == "yes"; then
185 185 PKG_CHECK_MODULES( [IPC3270], [ipc3270-static], AC_DEFINE(USING_STATIC_IPC3270), AC_MSG_ERROR([IPC3270 not present.]))
186 186 else
  187 + LDFLAGS="$LDFLAGS -Wl,-Bstatic,--whole-archive -lwinpthread -Wl,--no-whole-archive,-Bdynamic"
187 188 PKG_CHECK_MODULES( [IPC3270], [ipc3270], AC_DEFINE(USING_SHARED_IPC3270), AC_MSG_ERROR([IPC3270 not present.]))
188 189 fi
189 190  
... ...
py3270.cbp
... ... @@ -56,6 +56,8 @@
56 56 <Option compilerVar="CC" />
57 57 </Unit>
58 58 <Unit filename="src/module/properties.cc" />
  59 + <Unit filename="src/module/windows/init.cc" />
  60 + <Unit filename="src/module/windows/tools.cc" />
59 61 <Unit filename="src/session/actions.cc" />
60 62 <Unit filename="src/session/attributes.cc" />
61 63 <Unit filename="src/session/get.cc" />
... ...
src/include/py3270.h
... ... @@ -77,12 +77,14 @@
77 77 #include <stdexcept>
78 78 #include <system_error>
79 79 #include <vector>
  80 + #include <string>
80 81 #include <lib3270/ipc.h>
81 82 #include <lib3270/ipc/action.h>
82 83 #include <lib3270/actions.h>
83 84  
84 85 using std::exception;
85 86 using std::runtime_error;
  87 + using std::string;
86 88 using TN3270::Host;
87 89 using TN3270::Action;
88 90  
... ... @@ -93,6 +95,8 @@
93 95  
94 96 DLL_PRIVATE void py3270_wait(Host &host, PyObject *args);
95 97  
  98 + DLL_PRIVATE string py3270_get_datadir() noexcept;
  99 +
96 100 extern "C" {
97 101  
98 102 #else
... ... @@ -163,38 +167,6 @@
163 167 DLL_PRIVATE PyObject * py3270_action_get_activatable(PyObject *self, void *dunno);
164 168 DLL_PRIVATE PyObject * py3270_action_str(PyObject *self);
165 169  
166   - /*
167   -
168   - DLL_PRIVATE PyObject * py3270_alloc(PyTypeObject *type, PyObject *args, PyObject *kwds);
169   - DLL_PRIVATE int py3270_init(py3270_TerminalObject *self, PyObject *args, PyObject *kwds);
170   - DLL_PRIVATE void py3270_dealloc(py3270_TerminalObject * self);
171   -
172   - DLL_PRIVATE PyObject * terminal_get_version(PyObject *self, PyObject *args);
173   - DLL_PRIVATE PyObject * terminal_get_revision(PyObject *self, PyObject *args);
174   -
175   - DLL_PRIVATE PyObject * terminal_is_connected(PyObject *self, PyObject *args);
176   - DLL_PRIVATE PyObject * terminal_is_ready(PyObject *self, PyObject *args);
177   -
178   - DLL_PRIVATE PyObject * terminal_connect(PyObject *self, PyObject *args);
179   - DLL_PRIVATE PyObject * terminal_disconnect(PyObject *self, PyObject *args);
180   -
181   - DLL_PRIVATE PyObject * terminal_get_string_at(PyObject *self, PyObject *args);
182   - DLL_PRIVATE PyObject * terminal_get_contents(PyObject *self);
183   - DLL_PRIVATE PyObject * terminal_set_string_at(PyObject *self, PyObject *args);
184   - DLL_PRIVATE PyObject * terminal_cmp_string_at(PyObject *self, PyObject *args);
185   -
186   - DLL_PRIVATE PyObject * terminal_pfkey(PyObject *self, PyObject *args);
187   - DLL_PRIVATE PyObject * terminal_pakey(PyObject *self, PyObject *args);
188   - DLL_PRIVATE PyObject * terminal_enter(PyObject *self, PyObject *args);
189   - DLL_PRIVATE PyObject * terminal_action(PyObject *self, PyObject *args);
190   -
191   - DLL_PRIVATE PyObject * terminal_is_protected_at(PyObject *self, PyObject *args);
192   - DLL_PRIVATE PyObject * terminal_set_cursor_at(PyObject *self, PyObject *args);
193   -
194   - DLL_PRIVATE PyObject * terminal_wait_for_ready(PyObject *self, PyObject *args);
195   - DLL_PRIVATE PyObject * terminal_wait_for_string_at(PyObject *self, PyObject *args);
196   - */
197   -
198 170 #ifdef __cplusplus
199 171 }
200 172 #endif
... ...
src/module/windows/init.cc 0 → 100644
... ... @@ -0,0 +1,195 @@
  1 +/*
  2 + * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270
  3 + * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a
  4 + * aplicativos mainframe. Registro no INPI sob o nome G3270.
  5 + *
  6 + * Copyright (C) <2008> <Banco do Brasil S.A.>
  7 + *
  8 + * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob
  9 + * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela
  10 + * Free Software Foundation.
  11 + *
  12 + * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER
  13 + * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO
  14 + * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para
  15 + * obter mais detalhes.
  16 + *
  17 + * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este
  18 + * programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin
  19 + * St, Fifth Floor, Boston, MA 02110-1301 USA
  20 + *
  21 + * Este programa está nomeado como - e possui - linhas de código.
  22 + *
  23 + * Contatos:
  24 + *
  25 + * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck)
  26 + * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça)
  27 + *
  28 + */
  29 +
  30 +/**
  31 + * @file
  32 + *
  33 + * @brief Win32 delayed loading support methods.
  34 + *
  35 + * @author perry.werneck@gmail.com
  36 + *
  37 + */
  38 +
  39 + #include <config.h>
  40 + #include <winsock2.h>
  41 + #include <windows.h>
  42 + #include <py3270.h>
  43 + #include <lmcons.h>
  44 + #include <delayimp.h>
  45 + #include <fcntl.h>
  46 + #include <string>
  47 + #include <stdexcept>
  48 + #include <lib3270.h>
  49 +
  50 + #ifdef USING_STATIC_IPC3270
  51 +
  52 + extern "C" {
  53 +
  54 + extern __declspec (dllexport) PfnDliHook __pfnDliNotifyHook2;
  55 + extern __declspec (dllexport) PfnDliHook __pfnDliFailureHook2;
  56 +
  57 + FARPROC WINAPI py3270_delay_load_hook(unsigned reason, DelayLoadInfo * info);
  58 +
  59 + }
  60 +
  61 + using std::string;
  62 +
  63 +/*---[ Implement ]----------------------------------------------------------------------------------*/
  64 +
  65 + // https://docs.microsoft.com/en-us/cpp/build/reference/loading-all-imports-for-a-delay-loaded-dll?view=vs-2019
  66 +
  67 + PfnDliHook __pfnDliNotifyHook2 = py3270_delay_load_hook;
  68 + PfnDliHook __pfnDliFailureHook2 = py3270_delay_load_hook;
  69 +
  70 + static HANDLE hModule = 0;
  71 + static HANDLE hEventLog = 0;
  72 +
  73 + BOOL WINAPI DllMain(HANDLE hInstance, DWORD dwcallpurpose, LPVOID lpvResvd) {
  74 + switch(dwcallpurpose) {
  75 + case DLL_PROCESS_ATTACH:
  76 + hModule = hInstance;
  77 + hEventLog = RegisterEventSource(NULL, LIB3270_STRINGIZE_VALUE_OF(PRODUCT_NAME));
  78 + break;
  79 +
  80 + case DLL_PROCESS_DETACH:
  81 + hModule = 0;
  82 + DeregisterEventSource(hEventLog);
  83 + hEventLog = 0;
  84 + break;
  85 +
  86 + }
  87 +
  88 + return TRUE;
  89 + }
  90 +
  91 + static void eventlog(const char *msg) {
  92 +
  93 + char username[UNLEN + 1];
  94 + DWORD szName = sizeof(username);
  95 +
  96 + memset(username,0,UNLEN + 1);
  97 +
  98 + if(!GetUserName(username, &szName)) {
  99 + username[0] = 0;
  100 + }
  101 +
  102 + const char *outMsg[] = {
  103 + username,
  104 + PACKAGE_NAME,
  105 + msg
  106 + };
  107 +
  108 + debug("Event: \"%s\"",msg);
  109 +
  110 + ReportEvent(
  111 + hEventLog,
  112 + EVENTLOG_ERROR_TYPE,
  113 + 1,
  114 + 0,
  115 + NULL,
  116 + 3,
  117 + 0,
  118 + outMsg,
  119 + NULL
  120 + );
  121 +
  122 + }
  123 +
  124 + static void dummyProc() {
  125 + throw std::runtime_error("Operation not supported");
  126 + }
  127 +
  128 + FARPROC WINAPI py3270_delay_load_hook(unsigned reason, DelayLoadInfo * info) {
  129 +
  130 + static string savedpath;
  131 +
  132 + // https://docs.microsoft.com/en-us/cpp/build/reference/structure-and-constant-definitions?view=vs-2019
  133 + switch (reason) {
  134 + case dliNoteStartProcessing:
  135 + {
  136 +
  137 + string datadir = py3270_get_datadir();
  138 +
  139 + if(!datadir.empty()) {
  140 +
  141 + char curdir[4096];
  142 + memset(curdir,0,sizeof(curdir));
  143 +
  144 + if(GetCurrentDirectory(sizeof(curdir)-1,curdir)) {
  145 + savedpath = curdir;
  146 + } else {
  147 + savedpath.clear();
  148 + }
  149 +
  150 + SetCurrentDirectory(datadir.c_str());
  151 +
  152 + }
  153 +
  154 + }
  155 + break;
  156 +
  157 + case dliNoteEndProcessing:
  158 + if(!savedpath.empty()) {
  159 + SetCurrentDirectory(savedpath.c_str());
  160 + savedpath.clear();
  161 + }
  162 + break;
  163 +
  164 + case dliNotePreLoadLibrary:
  165 + break;
  166 +
  167 + case dliNotePreGetProcAddress:
  168 + break;
  169 +
  170 + case dliFailLoadLib:
  171 + {
  172 + string msg = "Can't load ";
  173 + msg += (const char *) info->szDll;
  174 + eventlog(msg.c_str());
  175 + }
  176 + return (FARPROC) hModule;
  177 +
  178 + case dliFailGetProc:
  179 + {
  180 + string msg = "Can't find method on ";
  181 + msg += (const char *) info->szDll;
  182 + eventlog(msg.c_str());
  183 + }
  184 + return (FARPROC) dummyProc;
  185 +
  186 + }
  187 +
  188 + // Returning NULL causes the delay load machinery to perform default
  189 + // processing for this notification.
  190 + return NULL;
  191 +
  192 + }
  193 +
  194 + #endif // USING_STATIC_IPC3270
  195 +
... ...
src/module/windows/tools.cc 0 → 100644
... ... @@ -0,0 +1,77 @@
  1 +/*
  2 + * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270
  3 + * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a
  4 + * aplicativos mainframe. Registro no INPI sob o nome G3270.
  5 + *
  6 + * Copyright (C) <2008> <Banco do Brasil S.A.>
  7 + *
  8 + * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob
  9 + * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela
  10 + * Free Software Foundation.
  11 + *
  12 + * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER
  13 + * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO
  14 + * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para
  15 + * obter mais detalhes.
  16 + *
  17 + * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este
  18 + * programa; se não, escreva para a Free Software Foundation, Inc., 59 Temple
  19 + * Place, Suite 330, Boston, MA, 02111-1307, USA
  20 + *
  21 + * Este programa está nomeado como - e possui - linhas de código.
  22 + *
  23 + * Contatos:
  24 + *
  25 + * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck)
  26 + * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça)
  27 + *
  28 + */
  29 +
  30 + #include <py3270.h>
  31 +
  32 +/*--[ Implement ]------------------------------------------------------------------------------------*/
  33 +
  34 + std::string py3270_get_datadir() noexcept {
  35 +
  36 + LSTATUS rc;
  37 + HKEY hKey = 0;
  38 + char datadir[4096];
  39 +
  40 + static const char * keys[] = {
  41 +
  42 + "Software\\" LIB3270_STRINGIZE_VALUE_OF(PRODUCT_NAME),
  43 + "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" LIB3270_STRINGIZE_VALUE_OF(PRODUCT_NAME),
  44 +
  45 +#ifdef LIB3270_NAME
  46 + "Software\\" LIB3270_STRINGIZE_VALUE_OF(LIB3270_NAME),
  47 + "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" LIB3270_STRINGIZE_VALUE_OF(LIB3270_NAME),
  48 +#endif
  49 +
  50 + "Software\\pw3270",
  51 + "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\pw3270"
  52 + };
  53 +
  54 + for(size_t ix = 0; !*datadir && ix < (sizeof(keys)/sizeof(keys[0])); ix++) {
  55 +
  56 + rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE,keys[ix],0,KEY_QUERY_VALUE,&hKey);
  57 + if(rc == ERROR_SUCCESS) {
  58 +
  59 + unsigned long datatype; // #defined in winnt.h (predefined types 0-11)
  60 + unsigned long datalen = sizeof(datadir);
  61 +
  62 + memset(datadir,0,datalen);
  63 +
  64 + rc = RegQueryValueExA(hKey,"InstallLocation",NULL,&datatype,(LPBYTE) datadir,&datalen);
  65 + if(rc != ERROR_SUCCESS) {
  66 + *datadir = 0; // Just in case
  67 + }
  68 +
  69 + RegCloseKey(hKey);
  70 +
  71 + }
  72 +
  73 + }
  74 +
  75 + return string(datadir);
  76 + }
  77 +
... ...