Commit 16a0f764450c2a92b5ca62f38b7d0190dffba5a1

Authored by Perry Werneck
1 parent 4a5dbd50
Exists in master and in 1 other branch develop

Reimplementing delayed loading on windows.

client/ipcclient.cbp
@@ -48,11 +48,13 @@ @@ -48,11 +48,13 @@
48 <Unit filename="src/core/linux/attribute.cc" /> 48 <Unit filename="src/core/linux/attribute.cc" />
49 <Unit filename="src/core/linux/request.cc" /> 49 <Unit filename="src/core/linux/request.cc" />
50 <Unit filename="src/core/session.cc" /> 50 <Unit filename="src/core/session.cc" />
  51 + <Unit filename="src/core/windows/attribute.cc" />
51 <Unit filename="src/core/windows/pop.cc" /> 52 <Unit filename="src/core/windows/pop.cc" />
52 <Unit filename="src/core/windows/push.cc" /> 53 <Unit filename="src/core/windows/push.cc" />
53 <Unit filename="src/core/windows/request.cc" /> 54 <Unit filename="src/core/windows/request.cc" />
54 <Unit filename="src/core/windows/resources.rc" /> 55 <Unit filename="src/core/windows/resources.rc" />
55 <Unit filename="src/core/windows/resources.rc.in" /> 56 <Unit filename="src/core/windows/resources.rc.in" />
  57 + <Unit filename="src/core/windows/tools.cc" />
56 <Unit filename="src/host/actions.cc" /> 58 <Unit filename="src/host/actions.cc" />
57 <Unit filename="src/host/init.cc" /> 59 <Unit filename="src/host/init.cc" />
58 <Unit filename="src/host/pop.cc" /> 60 <Unit filename="src/host/pop.cc" />
client/src/core/windows/tools.cc 0 → 100644
@@ -0,0 +1,194 @@ @@ -0,0 +1,194 @@
  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 convenience methods.
  34 + *
  35 + * @author perry.werneck@gmail.com
  36 + *
  37 + */
  38 +
  39 + #include <config.h>
  40 + #include <ipc-client-internals.h>
  41 + #include <lmcons.h>
  42 + #include <fcntl.h>
  43 +
  44 + using std::string;
  45 +
  46 +/*---[ Implement ]----------------------------------------------------------------------------------*/
  47 +
  48 + // https://docs.microsoft.com/en-us/cpp/build/reference/loading-all-imports-for-a-delay-loaded-dll?view=vs-2019
  49 +
  50 + PfnDliHook __pfnDliNotifyHook2 = IPC3270_DelayLoadHook;
  51 + PfnDliHook __pfnDliFailureHook2 = IPC3270_DelayLoadHook;
  52 +
  53 + FARPROC WINAPI IPC3270_DelayLoadHook(unsigned reason, DelayLoadInfo * info) {
  54 +
  55 + // https://docs.microsoft.com/en-us/cpp/build/reference/structure-and-constant-definitions?view=vs-2019
  56 +
  57 + debug(__FUNCTION__," ",(const char *) info->szDll);
  58 +
  59 + switch (reason) {
  60 + case dliNoteStartProcessing:
  61 + debug(__FUNCTION__,"::dliNoteStartProcessing")
  62 + /*
  63 + {
  64 + string installLocation = TN3270::getInstallLocation();
  65 + if(!installLocation.empty()) {
  66 + SetCurrentDirectory(installLocation.c_str());
  67 + }
  68 + }
  69 + */
  70 + break;
  71 +
  72 + case dliNoteEndProcessing:
  73 + debug(__FUNCTION__,"::dliNoteEndProcessing")
  74 + break;
  75 +
  76 + case dliNotePreLoadLibrary:
  77 + debug(__FUNCTION__,"::dliNotePreLoadLibrary");
  78 +
  79 + /*
  80 + {
  81 + // http://otb.manusoft.com/2013/01/using-delayload-to-specify-dependent-dll-path.htm
  82 +
  83 + string myPath = TN3270::getInstallLocation();
  84 +
  85 + myPath += "\\";
  86 + myPath += (const char *) info->szDll;
  87 +
  88 + debug("Checking ",myPath,"=",access(myPath.c_str(), R_OK));
  89 +
  90 + if(access(myPath.c_str(), R_OK) == 0) {
  91 + return (FARPROC) LoadLibrary(myPath.c_str());
  92 + }
  93 +
  94 + }
  95 + */
  96 + break;
  97 +
  98 + case dliNotePreGetProcAddress:
  99 + debug(__FUNCTION__,"::dliNotePreGetProcAddress")
  100 + break;
  101 +
  102 + case dliFailLoadLib:
  103 + debug(__FUNCTION__,"::dliFailLoadLib")
  104 + break;
  105 +
  106 + case dliFailGetProc:
  107 + debug(__FUNCTION__,"::dliFailGetProc")
  108 + break;
  109 +
  110 + default:
  111 + debug(__FUNCTION__,"::default")
  112 +
  113 + }
  114 +
  115 + // Returning NULL causes the delay load machinery to perform default
  116 + // processing for this notification.
  117 + return NULL;
  118 +
  119 + }
  120 +
  121 + namespace TN3270 {
  122 +
  123 + std::string getUserName() {
  124 +
  125 + char username[UNLEN + 1];
  126 + DWORD szName = sizeof(username);
  127 +
  128 + memset(username,0,UNLEN + 1);
  129 +
  130 + if(!GetUserName(username, &szName)) {
  131 + return "";
  132 + }
  133 +
  134 + return std::string(username);
  135 +
  136 + }
  137 +
  138 + std::string getInstallLocation() {
  139 +
  140 + LSTATUS rc;
  141 + HKEY hKey = 0;
  142 +
  143 + static const char * keys[] = {
  144 +
  145 + "Software\\" LIB3270_STRINGIZE_VALUE_OF(PRODUCT_NAME),
  146 + "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" LIB3270_STRINGIZE_VALUE_OF(PRODUCT_NAME),
  147 +
  148 +#ifdef LIB3270_NAME
  149 + "Software\\" LIB3270_STRINGIZE_VALUE_OF(LIB3270_NAME),
  150 + "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" LIB3270_STRINGIZE_VALUE_OF(LIB3270_NAME),
  151 +#endif
  152 +
  153 + "Software\\pw3270",
  154 + "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\pw3270"
  155 + };
  156 +
  157 + size_t ix;
  158 +
  159 + string installLocation;
  160 +
  161 + for(ix = 0; installLocation.empty() && ix < (sizeof(keys)/sizeof(keys[0])); ix++) {
  162 +
  163 + debug(ix,"=",keys[ix]);
  164 +
  165 + rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE,keys[ix],0,KEY_QUERY_VALUE,&hKey);
  166 + if(rc == ERROR_SUCCESS) {
  167 +
  168 + unsigned long datatype; // #defined in winnt.h (predefined types 0-11)
  169 + char datadir[4096];
  170 + unsigned long datalen = sizeof(datadir);
  171 +
  172 + memset(datadir,0,datalen);
  173 +
  174 + rc = RegQueryValueExA(hKey,"InstallLocation",NULL,&datatype,(LPBYTE) datadir,&datalen);
  175 + if(rc == ERROR_SUCCESS) {
  176 +
  177 + debug("Found: ",datadir);
  178 +
  179 + installLocation.assign(datadir);
  180 +
  181 + }
  182 +
  183 + RegCloseKey(hKey);
  184 +
  185 + }
  186 +
  187 + }
  188 +
  189 + return installLocation;
  190 + }
  191 +
  192 + }
  193 +
  194 +
client/src/include/ipc-client-internals.h
@@ -57,6 +57,7 @@ @@ -57,6 +57,7 @@
57 #include <lib3270/popup.h> 57 #include <lib3270/popup.h>
58 #include <system_error> 58 #include <system_error>
59 #include <stdexcept> 59 #include <stdexcept>
  60 + #include <string>
60 61
61 #ifdef HAVE_LIBINTL 62 #ifdef HAVE_LIBINTL
62 #include <libintl.h> 63 #include <libintl.h>
@@ -101,6 +102,14 @@ @@ -101,6 +102,14 @@
101 /// @brief Check lib3270 return codes, launch exception when failed. 102 /// @brief Check lib3270 return codes, launch exception when failed.
102 TN3270_PRIVATE void chkResponse(int rc); 103 TN3270_PRIVATE void chkResponse(int rc);
103 104
  105 +#ifdef _WIN32
  106 +
  107 + /// @brief Get protocol library install location.
  108 + TN3270_PRIVATE std::string getInstallLocation();
  109 + TN3270_PRIVATE std::string getUserName();
  110 +
  111 +#endif // _WIN32
  112 +
104 namespace Abstract { 113 namespace Abstract {
105 114
106 class TN3270_PRIVATE Session : public TN3270::Session { 115 class TN3270_PRIVATE Session : public TN3270::Session {
client/src/include/lib3270/ipc.h
@@ -40,6 +40,8 @@ @@ -40,6 +40,8 @@
40 40
41 #if defined(_WIN32) 41 #if defined(_WIN32)
42 42
  43 + #include <delayimp.h>
  44 +
43 #define TN3270_PUBLIC __declspec (dllexport) 45 #define TN3270_PUBLIC __declspec (dllexport)
44 #define TN3270_PRIVATE 46 #define TN3270_PRIVATE
45 47
@@ -63,6 +65,19 @@ @@ -63,6 +65,19 @@
63 65
64 #include <string> 66 #include <string>
65 67
  68 +#ifdef _WIN32
  69 +
  70 + extern "C" {
  71 +
  72 + extern __declspec (dllexport) PfnDliHook __pfnDliNotifyHook2;
  73 + extern __declspec (dllexport) PfnDliHook __pfnDliFailureHook2;
  74 +
  75 + FARPROC WINAPI IPC3270_DelayLoadHook(unsigned reason, DelayLoadInfo * info);
  76 +
  77 + }
  78 +
  79 +#endif // _WIN32
  80 +
66 namespace TN3270 { 81 namespace TN3270 {
67 82
68 class Host; 83 class Host;
client/src/session/local/init.cc
@@ -55,198 +55,10 @@ @@ -55,198 +55,10 @@
55 return new Local::Session(); 55 return new Local::Session();
56 } 56 }
57 57
58 - #ifdef _WIN32  
59 -  
60 - string getUserName() {  
61 -  
62 - char username[UNLEN + 1];  
63 - DWORD szName = sizeof(username);  
64 -  
65 - memset(username,0,UNLEN + 1);  
66 -  
67 - if(!GetUserName(username, &szName)) {  
68 - return "?";  
69 - }  
70 -  
71 - return string(username);  
72 -  
73 - }  
74 -  
75 - static void writeLog(HANDLE hEventLog, const char *msg, int rc = (int) GetLastError()) {  
76 -  
77 -  
78 - debug(msg," rc=",rc);  
79 -  
80 - if(hEventLog) {  
81 -  
82 - string username = getUserName();  
83 - char lasterror[1024];  
84 - snprintf(lasterror,sizeof(lasterror),"The error code was %d",rc);  
85 -  
86 - const char *outMsg[] = {  
87 - username.c_str(),  
88 - msg,  
89 - lasterror  
90 - };  
91 -  
92 - ReportEvent(  
93 - hEventLog,  
94 - EVENTLOG_ERROR_TYPE,  
95 - 1,  
96 - 0,  
97 - NULL,  
98 - (sizeof(outMsg) / sizeof(outMsg[0])),  
99 - 0,  
100 - outMsg,  
101 - NULL  
102 - );  
103 -  
104 - }  
105 -  
106 - }  
107 -  
108 - static string getInstallLocation(HANDLE hEventLog) {  
109 -  
110 - LSTATUS rc;  
111 - HKEY hKey = 0;  
112 -  
113 - static const char * keys[] = {  
114 -  
115 - "Software\\" LIB3270_STRINGIZE_VALUE_OF(PRODUCT_NAME),  
116 - "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" LIB3270_STRINGIZE_VALUE_OF(PRODUCT_NAME),  
117 -  
118 -#ifdef LIB3270_NAME  
119 - "Software\\" LIB3270_STRINGIZE_VALUE_OF(LIB3270_NAME),  
120 - "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" LIB3270_STRINGIZE_VALUE_OF(LIB3270_NAME),  
121 -#endif  
122 -  
123 - "Software\\pw3270",  
124 - "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\pw3270"  
125 - };  
126 -  
127 - size_t ix;  
128 -  
129 - string installLocation;  
130 -  
131 - for(ix = 0; installLocation.empty() && ix < (sizeof(keys)/sizeof(keys[0])); ix++) {  
132 -  
133 - debug(ix,"=",keys[ix]);  
134 -  
135 - rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE,keys[ix],0,KEY_QUERY_VALUE,&hKey);  
136 - if(rc == ERROR_SUCCESS) {  
137 -  
138 - unsigned long datatype; // #defined in winnt.h (predefined types 0-11)  
139 - char datadir[4096];  
140 - unsigned long datalen = sizeof(datadir);  
141 -  
142 - memset(datadir,0,datalen);  
143 -  
144 - rc = RegQueryValueExA(hKey,"InstallLocation",NULL,&datatype,(LPBYTE) datadir,&datalen);  
145 - if(rc == ERROR_SUCCESS) {  
146 -  
147 - debug("Found: ",datadir);  
148 -  
149 - installLocation.assign(datadir);  
150 - string username = getUserName();  
151 -  
152 - const char *outMsg[] = {  
153 - username.c_str(),  
154 - "Found LIB3270 installation",  
155 - keys[ix],  
156 - installLocation.c_str()  
157 - };  
158 -  
159 - ReportEvent(  
160 - hEventLog,  
161 - EVENTLOG_INFORMATION_TYPE,  
162 - 1,  
163 - 0,  
164 - NULL,  
165 - (sizeof(outMsg) / sizeof(outMsg[0])),  
166 - 0,  
167 - outMsg,  
168 - NULL  
169 - );  
170 -  
171 - }  
172 -  
173 - RegCloseKey(hKey);  
174 -  
175 - }  
176 -  
177 - }  
178 -  
179 - return installLocation;  
180 - }  
181 -  
182 - #endif // _WIN32  
183 -  
184 Local::Session::Session() : Abstract::Session() { 58 Local::Session::Session() : Abstract::Session() {
185 59
186 std::lock_guard<std::mutex> lock(sync); 60 std::lock_guard<std::mutex> lock(sync);
187 61
188 -#ifdef _WIN32  
189 - {  
190 - static bool initialized = false;  
191 -  
192 - if(!initialized) {  
193 -  
194 -#ifdef LIB3270_NAME  
195 - HANDLE hEventLog = RegisterEventSource(NULL, LIB3270_STRINGIZE_VALUE_OF(LIB3270_NAME));  
196 -#else  
197 - HANDLE hEventLog = RegisterEventSource(NULL, PACKAGE_NAME);  
198 -#endif // LIB3270_NAME  
199 -  
200 - string installLocation = getInstallLocation(hEventLog);  
201 -  
202 - if(installLocation.empty()) {  
203 -  
204 - writeLog(hEventLog, "Can't identify lib3270 installation path");  
205 -  
206 - } else {  
207 -  
208 - // TODO: Understand why SetDefaultDllDirectories & AddDllDirectory causes failure in DNS resolution.  
209 -  
210 -  
211 - SetCurrentDirectory(installLocation.c_str());  
212 -  
213 -/*  
214 - wchar_t *path = (wchar_t *) malloc(sizeof(datadir)*sizeof(wchar_t));  
215 - mbstowcs(path, datadir, 4095);  
216 -  
217 - if(!SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_USER_DIRS)) {  
218 - writeLog(hEventLog,"SetDefaultDllDirectories has failed");  
219 - }  
220 -#ifdef DEBUG  
221 - else {  
222 - debug("SetDefaultDllDirectories has suceeded");  
223 - }  
224 -#endif  
225 -  
226 - if(!AddDllDirectory(path)) {  
227 - string msg = "Can't add ";  
228 - msg += datadir;  
229 - msg += " to directory path";  
230 - writeLog(hEventLog,msg.c_str());  
231 - }  
232 -#ifdef DEBUG  
233 - else {  
234 - debug("AddDllDirectory has suceeded");  
235 - }  
236 -#endif  
237 - free(path);  
238 -  
239 -*/  
240 - }  
241 -  
242 - initialized = true;  
243 - DeregisterEventSource(hEventLog);  
244 -  
245 - }  
246 -  
247 - }  
248 -#endif // _WIN32  
249 -  
250 this->hSession = lib3270_session_new(""); 62 this->hSession = lib3270_session_new("");
251 63
252 lib3270_set_user_data(this->hSession,(void *) this); 64 lib3270_set_user_data(this->hSession,(void *) this);
@@ -263,6 +75,8 @@ @@ -263,6 +75,8 @@
263 75
264 cbk->update_connect = connectHandler; 76 cbk->update_connect = connectHandler;
265 77
  78 + throw std::runtime_error("Testando pre-load");
  79 +
266 } 80 }
267 81
268 Local::Session::~Session() { 82 Local::Session::~Session() {