changeset 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 7f5cf0fed473
children 46e45b4a4a03
files checker/checkcode.h src/helper.cpp
diffstat 2 files changed, 55 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/checker/checkcode.h	Wed Aug 29 17:40:36 2018 +0100
+++ b/checker/checkcode.h	Thu Aug 30 12:32:55 2018 +0100
@@ -46,9 +46,10 @@
      */
     FAIL_WRONG_ARCHITECTURE = 2,
 
-    /** Plugin library depends on some other library that cannot
-     *  be loaded. On Windows this may arise from system error 126,
-     *  ERROR_MOD_NOT_FOUND
+    /** Plugin library depends on some other library that cannot be
+     *  loaded. On Windows this may arise from system error 126,
+     *  ERROR_MOD_NOT_FOUND, provided that the library file itself
+     *  exists
      */
     FAIL_DEPENDENCY_MISSING = 3,
 
--- a/src/helper.cpp	Wed Aug 29 17:40:36 2018 +0100
+++ b/src/helper.cpp	Thu Aug 30 12:32:55 2018 +0100
@@ -93,7 +93,7 @@
 
 static std::string lastLibraryName = "";
 
-static HMODULE LoadLibraryUTF8(std::string name) {
+static HMODULE loadLibraryUTF8(std::string name) {
     lastLibraryName = name;
     int n = name.size();
     int wn = MultiByteToWideChar(CP_UTF8, 0, name.c_str(), n, 0, 0);
@@ -105,18 +105,23 @@
     return h;
 }
 
-static std::string GetErrorText() {
+static std::string getErrorText() {
     DWORD err = GetLastError();
-    wchar_t *buffer;
+    wchar_t *buffer = 0;
     FormatMessageW(
         FORMAT_MESSAGE_ALLOCATE_BUFFER |
         FORMAT_MESSAGE_FROM_SYSTEM |
         FORMAT_MESSAGE_IGNORE_INSERTS,
         NULL,
         err,
-        MAKELANGID(LANG_USER_DEFAULT, SUBLANG_USER_DEFAULT),
+        // the correct way to specify the user's default language,
+        // according to all resources I could find:
+        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
         (LPWSTR) &buffer,
         0, NULL );
+    if (!buffer) {
+        return "Unable to format error string (internal error)";
+    }
     int wn = wcslen(buffer);
     int n = WideCharToMultiByte(CP_UTF8, 0, buffer, wn, 0, 0, 0, 0);
     if (n < 0) {
@@ -129,6 +134,9 @@
     std::string s(text);
     LocalFree(&buffer);
     delete[] text;
+    if (s == "") {
+        return s;
+    }
     for (int i = s.size(); i > 0; ) {
         --i;
         if (s[i] == '\n' || s[i] == '\r') {
@@ -142,10 +150,27 @@
     return s;
 }
 
-#define DLOPEN(a,b)  LoadLibraryUTF8(a)
+#define DLOPEN(a,b)  loadLibraryUTF8(a)
 #define DLSYM(a,b)   (void *)GetProcAddress((HINSTANCE)(a),(b).c_str())
 #define DLCLOSE(a)   (!FreeLibrary((HINSTANCE)(a)))
-#define DLERROR()    (GetErrorText())
+#define DLERROR()    (getErrorText())
+
+static bool libraryExists(std::string name) {
+    if (name == "") return false;
+    int n = name.size();
+    int wn = MultiByteToWideChar(CP_UTF8, 0, name.c_str(), n, 0, 0);
+    wchar_t *wname = new wchar_t[wn+1];
+    wn = MultiByteToWideChar(CP_UTF8, 0, name.c_str(), n, wname, wn);
+    wname[wn] = L'\0';
+    FILE *f = _wfopen(wname, L"rb");
+    delete[] wname;
+    if (f) {
+        fclose(f);
+        return true;
+    } else {
+        return false;
+    }
+}
 
 #else
 
@@ -155,6 +180,17 @@
 #define DLCLOSE(a)   dlclose((a))
 #define DLERROR()    dlerror()
 
+static bool libraryExists(std::string name) {
+    if (name == "") return false;
+    FILE *f = fopen(name.c_str(), "r");
+    if (f) {
+        fclose(f);
+        return true;
+    } else {
+        return false;
+    }
+}
+
 #endif
 
 //#include <unistd.h>
@@ -202,7 +238,15 @@
         if (err == ERROR_BAD_EXE_FORMAT) {
             code = PluginCheckCode::FAIL_WRONG_ARCHITECTURE;
         } else if (err == ERROR_MOD_NOT_FOUND) {
-            code = PluginCheckCode::FAIL_DEPENDENCY_MISSING;
+            if (libraryExists(soname)) {
+                code = PluginCheckCode::FAIL_DEPENDENCY_MISSING;
+            } else {
+                code = PluginCheckCode::FAIL_LIBRARY_NOT_FOUND;
+            }
+        }
+#else
+        if (!libraryExists(soname)) {
+            code = PluginCheckCode::FAIL_LIBRARY_NOT_FOUND;
         }
 #endif
         return { code, message };