win_strerror.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. /*
  2. * Wrapper around the Windows FormatMessage system for retrieving the
  3. * text of a system error code, with a simple API similar to strerror.
  4. *
  5. * Works by keeping a tree234 containing mappings from system error
  6. * codes to strings. Entries allocated in this tree are simply never
  7. * freed.
  8. *
  9. * Also, the returned string has its trailing newline removed (so it
  10. * can go in places like the Event Log that never want a newline), and
  11. * is prefixed with the error number (so that if a user sends an error
  12. * report containing a translated error message we can't read, we can
  13. * still find out what the error actually was).
  14. */
  15. #include "putty.h"
  16. struct errstring {
  17. int error;
  18. char *text;
  19. };
  20. static int errstring_find(void *av, void *bv)
  21. {
  22. int *a = (int *)av;
  23. struct errstring *b = (struct errstring *)bv;
  24. if (*a < b->error)
  25. return -1;
  26. if (*a > b->error)
  27. return +1;
  28. return 0;
  29. }
  30. static int errstring_compare(void *av, void *bv)
  31. {
  32. struct errstring *a = (struct errstring *)av;
  33. return errstring_find(&a->error, bv);
  34. }
  35. static tree234 *errstrings = NULL;
  36. const char *win_strerror(int error)
  37. {
  38. struct errstring *es;
  39. if (!errstrings)
  40. errstrings = newtree234(errstring_compare);
  41. es = find234(errstrings, &error, errstring_find);
  42. if (!es) {
  43. char msgtext[65536]; /* maximum size for FormatMessage is 64K */
  44. es = snew(struct errstring);
  45. es->error = error;
  46. if (!FormatMessage((FORMAT_MESSAGE_FROM_SYSTEM |
  47. FORMAT_MESSAGE_IGNORE_INSERTS), NULL, error,
  48. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  49. msgtext, lenof(msgtext)-1, NULL)) {
  50. sprintf(msgtext,
  51. "(unable to format: FormatMessage returned %u)",
  52. (unsigned int)GetLastError());
  53. } else {
  54. int len = strlen(msgtext);
  55. if (len > 0 && msgtext[len-1] == '\n')
  56. msgtext[len-1] = '\0';
  57. }
  58. es->text = dupprintf("Error %d: %s", error, msgtext);
  59. add234(errstrings, es);
  60. }
  61. return es->text;
  62. }