Invent a win_strerror() function which behaves as much like Unix
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Mon, 22 Jul 2013 07:11:39 +0000 (07:11 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Mon, 22 Jul 2013 07:11:39 +0000 (07:11 +0000)
strerror as I can arrange, wrapping up all the ugly FormatMessage
nonsense and caching previously looked-up messages for reuse so that
callers can treat them as static.

git-svn-id: svn://svn.tartarus.org/sgt/putty@9956 cda61777-01e9-0310-a592-d414129be87e

windows/winmisc.c
windows/winstuff.h

index c74f1e7..525d52c 100644 (file)
@@ -173,6 +173,69 @@ HMODULE load_system32_dll(const char *libname)
     return ret;
 }
 
+/*
+ * A tree234 containing mappings from system error codes to strings.
+ */
+
+struct errstring {
+    int error;
+    char *text;
+};
+
+static int errstring_find(void *av, void *bv)
+{
+    int *a = (int *)av;
+    struct errstring *b = (struct errstring *)bv;
+    if (*a < b->error)
+        return -1;
+    if (*a > b->error)
+        return +1;
+    return 0;
+}
+static int errstring_compare(void *av, void *bv)
+{
+    struct errstring *a = (struct errstring *)av;
+    return errstring_find(&a->error, bv);
+}
+
+static tree234 *errstrings = NULL;
+
+const char *win_strerror(int error)
+{
+    struct errstring *es;
+
+    if (!errstrings)
+        errstrings = newtree234(errstring_compare);
+
+    es = find234(errstrings, &error, errstring_find);
+
+    if (!es) {
+        int bufsize, bufused;
+
+        es = snew(struct errstring);
+        es->error = error;
+        /* maximum size for FormatMessage is 64K */
+        bufsize = 65535;
+        es->text = snewn(bufsize, char);
+        if (!FormatMessage((FORMAT_MESSAGE_FROM_SYSTEM |
+                            FORMAT_MESSAGE_IGNORE_INSERTS), NULL, error,
+                           MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                           es->text + bufused, bufsize - bufused, NULL)) {
+            sprintf(es->text,
+                    "Windows error code %d (and FormatMessage returned %d)", 
+                    error, GetLastError());
+        } else {
+            int len = strlen(es->text);
+            if (len > 0 && es->text[len-1] == '\n')
+                es->text[len-1] = '\0';
+        }
+        es->text = sresize(es->text, strlen(es->text) + 1, char);
+        add234(errstrings, es);
+    }
+
+    return es->text;
+}
+
 #ifdef DEBUG
 static FILE *debug_fp = NULL;
 static HANDLE debug_hdl = INVALID_HANDLE_VALUE;
index cfed048..6571172 100644 (file)
@@ -461,6 +461,7 @@ void show_help(HWND hwnd);
 extern OSVERSIONINFO osVersion;
 BOOL init_winver(void);
 HMODULE load_system32_dll(const char *libname);
+const char *win_strerror(int error);
 
 /*
  * Exports from sizetip.c.