summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorawr1 <41453959+awr1@users.noreply.github.com>2020-04-16 13:23:54 -0500
committerGitHub <noreply@github.com>2020-04-16 20:23:54 +0200
commitb6f99409a967baebfda056a46f236643837e483b (patch)
treeb7f13efa7b576bdfcbaaaeb43263477e35fdb2c3
parent06e0c75ba9cd46cbbb09deb91db6f746fb62a820 (diff)
downloadNim-b6f99409a967baebfda056a46f236643837e483b.tar.gz
added extended msg for failed library loads w/ incorrect DLL formats (#13950)
* added extended msg for failed library loads w/ incorrect DLL formats

* missing colon

* fix GetLastError()

* make GetLastError() available for windows console apps

* remove premature nullchar if outputting extra message

* if-protect nullchar detection

* better fix for message box code
-rw-r--r--lib/system/dyncalls.nim36
-rw-r--r--lib/system/excpt.nim6
2 files changed, 30 insertions, 12 deletions
diff --git a/lib/system/dyncalls.nim b/lib/system/dyncalls.nim
index d16dbdf92..fe4797c5f 100644
--- a/lib/system/dyncalls.nim
+++ b/lib/system/dyncalls.nim
@@ -19,18 +19,34 @@ const
 
 proc nimLoadLibraryError(path: string) =
   # carefully written to avoid memory allocation:
-  cstderr.rawWrite("could not load: ")
+  const prefix = "could not load: "
+  cstderr.rawWrite(prefix)
   cstderr.rawWrite(path)
-  cstderr.rawWrite("\n")
   when not defined(nimDebugDlOpen) and not defined(windows):
-    cstderr.rawWrite("compile with -d:nimDebugDlOpen for more information\n")
-  when defined(windows) and defined(guiapp):
-    # Because console output is not shown in GUI apps, display error as message box:
-    const prefix = "could not load: "
-    var msg: array[1000, char]
-    copyMem(msg[0].addr, prefix.cstring, prefix.len)
-    copyMem(msg[prefix.len].addr, path.cstring, min(path.len + 1, 1000 - prefix.len))
-    discard MessageBoxA(nil, msg[0].addr, nil, 0)
+    cstderr.rawWrite("\n(compile with -d:nimDebugDlOpen for more information)")
+  when defined(windows):
+    const badExe = "\n(bad format; library may be wrong architecture)"
+    let loadError = GetLastError()
+    if loadError == ERROR_BAD_EXE_FORMAT:
+      cstderr.rawWrite(badExe)
+    when defined(guiapp):
+      # Because console output is not shown in GUI apps, display the error as a
+      # message box instead:
+      var
+        msg: array[1000, char]
+        msgLeft = msg.len - 1 # leave (at least) one for nullchar
+        msgIdx = 0
+      copyMem(msg[msgIdx].addr, prefix.cstring, prefix.len)
+      msgLeft -= prefix.len
+      msgIdx += prefix.len
+      let pathLen = min(path.len, msgLeft)
+      copyMem(msg[msgIdx].addr, path.cstring, pathLen)
+      msgLeft -= pathLen
+      msgIdx += pathLen
+      if loadError == ERROR_BAD_EXE_FORMAT and msgLeft >= badExe.len:
+        copyMem(msg[msgIdx].addr, badExe.cstring, badExe.len)
+      discard MessageBoxA(nil, msg[0].addr, nil, 0)
+  cstderr.rawWrite("\n")
   quit(1)
 
 proc procAddrError(name: cstring) {.compilerproc, nonReloadable, hcrInline.} =
diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim
index 76d188ea6..aa3667226 100644
--- a/lib/system/excpt.nim
+++ b/lib/system/excpt.nim
@@ -17,13 +17,15 @@ var
     ## instead of `stdmsg.write` when printing stacktrace.
     ## Unstable API.
 
+when defined(windows):
+  proc GetLastError(): int32 {.header: "<windows.h>", nodecl.}
+  const ERROR_BAD_EXE_FORMAT = 193
+
 when not defined(windows) or not defined(guiapp):
   proc writeToStdErr(msg: cstring) = rawWrite(cstderr, msg)
-
 else:
   proc MessageBoxA(hWnd: pointer, lpText, lpCaption: cstring, uType: int): int32 {.
     header: "<windows.h>", nodecl.}
-
   proc writeToStdErr(msg: cstring) =
     discard MessageBoxA(nil, msg, nil, 0)