comparison src/helper.cpp @ 42:49946b02414e errorcode

Further error checking - distinguish between library and dependency absent
author Chris Cannam
date Thu, 30 Aug 2018 12:32:55 +0100
parents 40c6936c2fc9
children d7ec0b2a8802
comparison
equal deleted inserted replaced
41:7f5cf0fed473 42:49946b02414e
91 #error "This must be compiled with UNICODE defined" 91 #error "This must be compiled with UNICODE defined"
92 #endif 92 #endif
93 93
94 static std::string lastLibraryName = ""; 94 static std::string lastLibraryName = "";
95 95
96 static HMODULE LoadLibraryUTF8(std::string name) { 96 static HMODULE loadLibraryUTF8(std::string name) {
97 lastLibraryName = name; 97 lastLibraryName = name;
98 int n = name.size(); 98 int n = name.size();
99 int wn = MultiByteToWideChar(CP_UTF8, 0, name.c_str(), n, 0, 0); 99 int wn = MultiByteToWideChar(CP_UTF8, 0, name.c_str(), n, 0, 0);
100 wchar_t *wname = new wchar_t[wn+1]; 100 wchar_t *wname = new wchar_t[wn+1];
101 wn = MultiByteToWideChar(CP_UTF8, 0, name.c_str(), n, wname, wn); 101 wn = MultiByteToWideChar(CP_UTF8, 0, name.c_str(), n, wname, wn);
103 HMODULE h = LoadLibraryW(wname); 103 HMODULE h = LoadLibraryW(wname);
104 delete[] wname; 104 delete[] wname;
105 return h; 105 return h;
106 } 106 }
107 107
108 static std::string GetErrorText() { 108 static std::string getErrorText() {
109 DWORD err = GetLastError(); 109 DWORD err = GetLastError();
110 wchar_t *buffer; 110 wchar_t *buffer = 0;
111 FormatMessageW( 111 FormatMessageW(
112 FORMAT_MESSAGE_ALLOCATE_BUFFER | 112 FORMAT_MESSAGE_ALLOCATE_BUFFER |
113 FORMAT_MESSAGE_FROM_SYSTEM | 113 FORMAT_MESSAGE_FROM_SYSTEM |
114 FORMAT_MESSAGE_IGNORE_INSERTS, 114 FORMAT_MESSAGE_IGNORE_INSERTS,
115 NULL, 115 NULL,
116 err, 116 err,
117 MAKELANGID(LANG_USER_DEFAULT, SUBLANG_USER_DEFAULT), 117 // the correct way to specify the user's default language,
118 // according to all resources I could find:
119 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
118 (LPWSTR) &buffer, 120 (LPWSTR) &buffer,
119 0, NULL ); 121 0, NULL );
122 if (!buffer) {
123 return "Unable to format error string (internal error)";
124 }
120 int wn = wcslen(buffer); 125 int wn = wcslen(buffer);
121 int n = WideCharToMultiByte(CP_UTF8, 0, buffer, wn, 0, 0, 0, 0); 126 int n = WideCharToMultiByte(CP_UTF8, 0, buffer, wn, 0, 0, 0, 0);
122 if (n < 0) { 127 if (n < 0) {
123 LocalFree(&buffer); 128 LocalFree(&buffer);
124 return "Unable to convert error string (internal error)"; 129 return "Unable to convert error string (internal error)";
127 (void)WideCharToMultiByte(CP_UTF8, 0, buffer, wn, text, n, 0, 0); 132 (void)WideCharToMultiByte(CP_UTF8, 0, buffer, wn, text, n, 0, 0);
128 text[n] = '\0'; 133 text[n] = '\0';
129 std::string s(text); 134 std::string s(text);
130 LocalFree(&buffer); 135 LocalFree(&buffer);
131 delete[] text; 136 delete[] text;
137 if (s == "") {
138 return s;
139 }
132 for (int i = s.size(); i > 0; ) { 140 for (int i = s.size(); i > 0; ) {
133 --i; 141 --i;
134 if (s[i] == '\n' || s[i] == '\r') { 142 if (s[i] == '\n' || s[i] == '\r') {
135 s.erase(i, 1); 143 s.erase(i, 1);
136 } 144 }
140 s.replace(pos, 2, lastLibraryName); 148 s.replace(pos, 2, lastLibraryName);
141 } 149 }
142 return s; 150 return s;
143 } 151 }
144 152
145 #define DLOPEN(a,b) LoadLibraryUTF8(a) 153 #define DLOPEN(a,b) loadLibraryUTF8(a)
146 #define DLSYM(a,b) (void *)GetProcAddress((HINSTANCE)(a),(b).c_str()) 154 #define DLSYM(a,b) (void *)GetProcAddress((HINSTANCE)(a),(b).c_str())
147 #define DLCLOSE(a) (!FreeLibrary((HINSTANCE)(a))) 155 #define DLCLOSE(a) (!FreeLibrary((HINSTANCE)(a)))
148 #define DLERROR() (GetErrorText()) 156 #define DLERROR() (getErrorText())
157
158 static bool libraryExists(std::string name) {
159 if (name == "") return false;
160 int n = name.size();
161 int wn = MultiByteToWideChar(CP_UTF8, 0, name.c_str(), n, 0, 0);
162 wchar_t *wname = new wchar_t[wn+1];
163 wn = MultiByteToWideChar(CP_UTF8, 0, name.c_str(), n, wname, wn);
164 wname[wn] = L'\0';
165 FILE *f = _wfopen(wname, L"rb");
166 delete[] wname;
167 if (f) {
168 fclose(f);
169 return true;
170 } else {
171 return false;
172 }
173 }
149 174
150 #else 175 #else
151 176
152 #include <dlfcn.h> 177 #include <dlfcn.h>
153 #define DLOPEN(a,b) dlopen((a).c_str(),(b)) 178 #define DLOPEN(a,b) dlopen((a).c_str(),(b))
154 #define DLSYM(a,b) dlsym((a),(b).c_str()) 179 #define DLSYM(a,b) dlsym((a),(b).c_str())
155 #define DLCLOSE(a) dlclose((a)) 180 #define DLCLOSE(a) dlclose((a))
156 #define DLERROR() dlerror() 181 #define DLERROR() dlerror()
182
183 static bool libraryExists(std::string name) {
184 if (name == "") return false;
185 FILE *f = fopen(name.c_str(), "r");
186 if (f) {
187 fclose(f);
188 return true;
189 } else {
190 return false;
191 }
192 }
157 193
158 #endif 194 #endif
159 195
160 //#include <unistd.h> 196 //#include <unistd.h>
161 197
200 #ifdef _WIN32 236 #ifdef _WIN32
201 DWORD err = GetLastError(); 237 DWORD err = GetLastError();
202 if (err == ERROR_BAD_EXE_FORMAT) { 238 if (err == ERROR_BAD_EXE_FORMAT) {
203 code = PluginCheckCode::FAIL_WRONG_ARCHITECTURE; 239 code = PluginCheckCode::FAIL_WRONG_ARCHITECTURE;
204 } else if (err == ERROR_MOD_NOT_FOUND) { 240 } else if (err == ERROR_MOD_NOT_FOUND) {
205 code = PluginCheckCode::FAIL_DEPENDENCY_MISSING; 241 if (libraryExists(soname)) {
242 code = PluginCheckCode::FAIL_DEPENDENCY_MISSING;
243 } else {
244 code = PluginCheckCode::FAIL_LIBRARY_NOT_FOUND;
245 }
246 }
247 #else
248 if (!libraryExists(soname)) {
249 code = PluginCheckCode::FAIL_LIBRARY_NOT_FOUND;
206 } 250 }
207 #endif 251 #endif
208 return { code, message }; 252 return { code, message };
209 } 253 }
210 254