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 48 <Unit filename="src/core/linux/attribute.cc" />
49 49 <Unit filename="src/core/linux/request.cc" />
50 50 <Unit filename="src/core/session.cc" />
  51 + <Unit filename="src/core/windows/attribute.cc" />
51 52 <Unit filename="src/core/windows/pop.cc" />
52 53 <Unit filename="src/core/windows/push.cc" />
53 54 <Unit filename="src/core/windows/request.cc" />
54 55 <Unit filename="src/core/windows/resources.rc" />
55 56 <Unit filename="src/core/windows/resources.rc.in" />
  57 + <Unit filename="src/core/windows/tools.cc" />
56 58 <Unit filename="src/host/actions.cc" />
57 59 <Unit filename="src/host/init.cc" />
58 60 <Unit filename="src/host/pop.cc" />
... ...
client/src/core/windows/tools.cc 0 → 100644
... ... @@ -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 57 #include <lib3270/popup.h>
58 58 #include <system_error>
59 59 #include <stdexcept>
  60 + #include <string>
60 61  
61 62 #ifdef HAVE_LIBINTL
62 63 #include <libintl.h>
... ... @@ -101,6 +102,14 @@
101 102 /// @brief Check lib3270 return codes, launch exception when failed.
102 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 113 namespace Abstract {
105 114  
106 115 class TN3270_PRIVATE Session : public TN3270::Session {
... ...
client/src/include/lib3270/ipc.h
... ... @@ -40,6 +40,8 @@
40 40  
41 41 #if defined(_WIN32)
42 42  
  43 + #include <delayimp.h>
  44 +
43 45 #define TN3270_PUBLIC __declspec (dllexport)
44 46 #define TN3270_PRIVATE
45 47  
... ... @@ -63,6 +65,19 @@
63 65  
64 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 81 namespace TN3270 {
67 82  
68 83 class Host;
... ...
client/src/session/local/init.cc
... ... @@ -55,198 +55,10 @@
55 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 58 Local::Session::Session() : Abstract::Session() {
185 59  
186 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 62 this->hSession = lib3270_session_new("");
251 63  
252 64 lib3270_set_user_data(this->hSession,(void *) this);
... ... @@ -263,6 +75,8 @@
263 75  
264 76 cbk->update_connect = connectHandler;
265 77  
  78 + throw std::runtime_error("Testando pre-load");
  79 +
266 80 }
267 81  
268 82 Local::Session::~Session() {
... ...