Commit 249d46fd03bd3337aaa27334041a110ab58294ad

Authored by Perry Werneck
1 parent ccd4292a
Exists in master

Adding methods for windows delayed loading.

@@ -101,7 +101,7 @@ case "$host" in @@ -101,7 +101,7 @@ case "$host" in
101 CFLAGS="$CFLAGS -pthread -D_WIN32_WINNT=0x0600" 101 CFLAGS="$CFLAGS -pthread -D_WIN32_WINNT=0x0600"
102 CXXFLAGS="$CXXFLAGS -pthread -D_WIN32_WINNT=0x0600" 102 CXXFLAGS="$CXXFLAGS -pthread -D_WIN32_WINNT=0x0600"
103 LIBS="$LIBS -lws2_32 -lwtsapi32 -lcomdlg32" 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 DLLEXT=".dll" 105 DLLEXT=".dll"
106 106
107 app_win32_revision=$(date +%-y.%-m.%-d.%-H) 107 app_win32_revision=$(date +%-y.%-m.%-d.%-H)
@@ -184,6 +184,7 @@ AC_ARG_WITH([static-ipc3270], @@ -184,6 +184,7 @@ AC_ARG_WITH([static-ipc3270],
184 if test "$app_cv_static_ipc3270" == "yes"; then 184 if test "$app_cv_static_ipc3270" == "yes"; then
185 PKG_CHECK_MODULES( [IPC3270], [ipc3270-static], AC_DEFINE(USING_STATIC_IPC3270), AC_MSG_ERROR([IPC3270 not present.])) 185 PKG_CHECK_MODULES( [IPC3270], [ipc3270-static], AC_DEFINE(USING_STATIC_IPC3270), AC_MSG_ERROR([IPC3270 not present.]))
186 else 186 else
  187 + LDFLAGS="$LDFLAGS -Wl,-Bstatic,--whole-archive -lwinpthread -Wl,--no-whole-archive,-Bdynamic"
187 PKG_CHECK_MODULES( [IPC3270], [ipc3270], AC_DEFINE(USING_SHARED_IPC3270), AC_MSG_ERROR([IPC3270 not present.])) 188 PKG_CHECK_MODULES( [IPC3270], [ipc3270], AC_DEFINE(USING_SHARED_IPC3270), AC_MSG_ERROR([IPC3270 not present.]))
188 fi 189 fi
189 190
@@ -56,6 +56,8 @@ @@ -56,6 +56,8 @@
56 <Option compilerVar="CC" /> 56 <Option compilerVar="CC" />
57 </Unit> 57 </Unit>
58 <Unit filename="src/module/properties.cc" /> 58 <Unit filename="src/module/properties.cc" />
  59 + <Unit filename="src/module/windows/init.cc" />
  60 + <Unit filename="src/module/windows/tools.cc" />
59 <Unit filename="src/session/actions.cc" /> 61 <Unit filename="src/session/actions.cc" />
60 <Unit filename="src/session/attributes.cc" /> 62 <Unit filename="src/session/attributes.cc" />
61 <Unit filename="src/session/get.cc" /> 63 <Unit filename="src/session/get.cc" />
src/include/py3270.h
@@ -77,12 +77,14 @@ @@ -77,12 +77,14 @@
77 #include <stdexcept> 77 #include <stdexcept>
78 #include <system_error> 78 #include <system_error>
79 #include <vector> 79 #include <vector>
  80 + #include <string>
80 #include <lib3270/ipc.h> 81 #include <lib3270/ipc.h>
81 #include <lib3270/ipc/action.h> 82 #include <lib3270/ipc/action.h>
82 #include <lib3270/actions.h> 83 #include <lib3270/actions.h>
83 84
84 using std::exception; 85 using std::exception;
85 using std::runtime_error; 86 using std::runtime_error;
  87 + using std::string;
86 using TN3270::Host; 88 using TN3270::Host;
87 using TN3270::Action; 89 using TN3270::Action;
88 90
@@ -93,6 +95,8 @@ @@ -93,6 +95,8 @@
93 95
94 DLL_PRIVATE void py3270_wait(Host &host, PyObject *args); 96 DLL_PRIVATE void py3270_wait(Host &host, PyObject *args);
95 97
  98 + DLL_PRIVATE string py3270_get_datadir() noexcept;
  99 +
96 extern "C" { 100 extern "C" {
97 101
98 #else 102 #else
@@ -163,38 +167,6 @@ @@ -163,38 +167,6 @@
163 DLL_PRIVATE PyObject * py3270_action_get_activatable(PyObject *self, void *dunno); 167 DLL_PRIVATE PyObject * py3270_action_get_activatable(PyObject *self, void *dunno);
164 DLL_PRIVATE PyObject * py3270_action_str(PyObject *self); 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 #ifdef __cplusplus 170 #ifdef __cplusplus
199 } 171 }
200 #endif 172 #endif
src/module/windows/init.cc 0 → 100644
@@ -0,0 +1,195 @@ @@ -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 @@ @@ -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 +