misc_win32.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. #include <malloc.h> /* for alloca() */
  2. /************************************************************/
  3. /* errno and GetLastError support */
  4. #include "misc_thread_common.h"
  5. static DWORD cffi_tls_index = TLS_OUT_OF_INDEXES;
  6. static void init_cffi_tls(void)
  7. {
  8. if (cffi_tls_index == TLS_OUT_OF_INDEXES) {
  9. cffi_tls_index = TlsAlloc();
  10. if (cffi_tls_index == TLS_OUT_OF_INDEXES)
  11. PyErr_SetString(PyExc_WindowsError, "TlsAlloc() failed");
  12. }
  13. }
  14. static struct cffi_tls_s *get_cffi_tls(void)
  15. {
  16. LPVOID p = TlsGetValue(cffi_tls_index);
  17. if (p == NULL) {
  18. p = malloc(sizeof(struct cffi_tls_s));
  19. if (p == NULL)
  20. return NULL;
  21. memset(p, 0, sizeof(struct cffi_tls_s));
  22. TlsSetValue(cffi_tls_index, p);
  23. }
  24. return (struct cffi_tls_s *)p;
  25. }
  26. #ifdef USE__THREAD
  27. # error "unexpected USE__THREAD on Windows"
  28. #endif
  29. static void save_errno(void)
  30. {
  31. int current_err = errno;
  32. int current_lasterr = GetLastError();
  33. struct cffi_tls_s *p = get_cffi_tls();
  34. if (p != NULL) {
  35. p->saved_errno = current_err;
  36. p->saved_lasterror = current_lasterr;
  37. }
  38. /* else: cannot report the error */
  39. }
  40. static void restore_errno(void)
  41. {
  42. struct cffi_tls_s *p = get_cffi_tls();
  43. if (p != NULL) {
  44. SetLastError(p->saved_lasterror);
  45. errno = p->saved_errno;
  46. }
  47. /* else: cannot report the error */
  48. }
  49. /************************************************************/
  50. #if PY_MAJOR_VERSION >= 3
  51. static PyObject *b_getwinerror(PyObject *self, PyObject *args, PyObject *kwds)
  52. {
  53. int err = -1;
  54. int len;
  55. WCHAR *s_buf = NULL; /* Free via LocalFree */
  56. PyObject *v, *message;
  57. static char *keywords[] = {"code", NULL};
  58. if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", keywords, &err))
  59. return NULL;
  60. if (err == -1) {
  61. struct cffi_tls_s *p = get_cffi_tls();
  62. if (p == NULL)
  63. return PyErr_NoMemory();
  64. err = p->saved_lasterror;
  65. }
  66. len = FormatMessageW(
  67. /* Error API error */
  68. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  69. FORMAT_MESSAGE_FROM_SYSTEM |
  70. FORMAT_MESSAGE_IGNORE_INSERTS,
  71. NULL, /* no message source */
  72. err,
  73. MAKELANGID(LANG_NEUTRAL,
  74. SUBLANG_DEFAULT), /* Default language */
  75. (LPWSTR) &s_buf,
  76. 0, /* size not used */
  77. NULL); /* no args */
  78. if (len==0) {
  79. /* Only seen this in out of mem situations */
  80. message = PyUnicode_FromFormat("Windows Error 0x%X", err);
  81. } else {
  82. /* remove trailing cr/lf and dots */
  83. while (len > 0 && (s_buf[len-1] <= L' ' || s_buf[len-1] == L'.'))
  84. s_buf[--len] = L'\0';
  85. message = PyUnicode_FromWideChar(s_buf, len);
  86. }
  87. if (message != NULL) {
  88. v = Py_BuildValue("(iO)", err, message);
  89. Py_DECREF(message);
  90. }
  91. else
  92. v = NULL;
  93. LocalFree(s_buf);
  94. return v;
  95. }
  96. #else
  97. static PyObject *b_getwinerror(PyObject *self, PyObject *args, PyObject *kwds)
  98. {
  99. int err = -1;
  100. int len;
  101. char *s;
  102. char *s_buf = NULL; /* Free via LocalFree */
  103. char s_small_buf[40]; /* Room for "Windows Error 0xFFFFFFFFFFFFFFFF" */
  104. PyObject *v;
  105. static char *keywords[] = {"code", NULL};
  106. if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", keywords, &err))
  107. return NULL;
  108. if (err == -1) {
  109. struct cffi_tls_s *p = get_cffi_tls();
  110. if (p == NULL)
  111. return PyErr_NoMemory();
  112. err = p->saved_lasterror;
  113. }
  114. len = FormatMessage(
  115. /* Error API error */
  116. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  117. FORMAT_MESSAGE_FROM_SYSTEM |
  118. FORMAT_MESSAGE_IGNORE_INSERTS,
  119. NULL, /* no message source */
  120. err,
  121. MAKELANGID(LANG_NEUTRAL,
  122. SUBLANG_DEFAULT), /* Default language */
  123. (LPTSTR) &s_buf,
  124. 0, /* size not used */
  125. NULL); /* no args */
  126. if (len==0) {
  127. /* Only seen this in out of mem situations */
  128. sprintf(s_small_buf, "Windows Error 0x%X", err);
  129. s = s_small_buf;
  130. } else {
  131. s = s_buf;
  132. /* remove trailing cr/lf and dots */
  133. while (len > 0 && (s[len-1] <= ' ' || s[len-1] == '.'))
  134. s[--len] = '\0';
  135. }
  136. v = Py_BuildValue("(is)", err, s);
  137. LocalFree(s_buf);
  138. return v;
  139. }
  140. #endif
  141. /************************************************************/
  142. /* Emulate dlopen()&co. from the Windows API */
  143. #define RTLD_LAZY 0
  144. #define RTLD_NOW 0
  145. #define RTLD_GLOBAL 0
  146. #define RTLD_LOCAL 0
  147. static void *dlopen(const char *filename, int flag)
  148. {
  149. return (void *)LoadLibraryA(filename);
  150. }
  151. static void *dlopenW(const wchar_t *filename)
  152. {
  153. return (void *)LoadLibraryW(filename);
  154. }
  155. static void *dlsym(void *handle, const char *symbol)
  156. {
  157. void *address = GetProcAddress((HMODULE)handle, symbol);
  158. #ifndef MS_WIN64
  159. if (!address) {
  160. /* If 'symbol' is not found, then try '_symbol@N' for N in
  161. (0, 4, 8, 12, ..., 124). Unlike ctypes, we try to do that
  162. for any symbol, although in theory it should only be done
  163. for __stdcall functions.
  164. */
  165. int i;
  166. char *mangled_name = alloca(1 + strlen(symbol) + 1 + 3 + 1);
  167. if (!mangled_name)
  168. return NULL;
  169. for (i = 0; i < 32; i++) {
  170. sprintf(mangled_name, "_%s@%d", symbol, i * 4);
  171. address = GetProcAddress((HMODULE)handle, mangled_name);
  172. if (address)
  173. break;
  174. }
  175. }
  176. #endif
  177. return address;
  178. }
  179. static int dlclose(void *handle)
  180. {
  181. return FreeLibrary((HMODULE)handle) ? 0 : -1;
  182. }
  183. static const char *dlerror(void)
  184. {
  185. static char buf[32];
  186. DWORD dw = GetLastError();
  187. if (dw == 0)
  188. return NULL;
  189. sprintf(buf, "error 0x%x", (unsigned int)dw);
  190. return buf;
  191. }