123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 |
- #include <malloc.h> /* for alloca() */
- /************************************************************/
- /* errno and GetLastError support */
- #include "misc_thread_common.h"
- static DWORD cffi_tls_index = TLS_OUT_OF_INDEXES;
- static void init_cffi_tls(void)
- {
- if (cffi_tls_index == TLS_OUT_OF_INDEXES) {
- cffi_tls_index = TlsAlloc();
- if (cffi_tls_index == TLS_OUT_OF_INDEXES)
- PyErr_SetString(PyExc_WindowsError, "TlsAlloc() failed");
- }
- }
- static struct cffi_tls_s *get_cffi_tls(void)
- {
- LPVOID p = TlsGetValue(cffi_tls_index);
- if (p == NULL) {
- p = malloc(sizeof(struct cffi_tls_s));
- if (p == NULL)
- return NULL;
- memset(p, 0, sizeof(struct cffi_tls_s));
- TlsSetValue(cffi_tls_index, p);
- }
- return (struct cffi_tls_s *)p;
- }
- #ifdef USE__THREAD
- # error "unexpected USE__THREAD on Windows"
- #endif
- static void save_errno(void)
- {
- int current_err = errno;
- int current_lasterr = GetLastError();
- struct cffi_tls_s *p = get_cffi_tls();
- if (p != NULL) {
- p->saved_errno = current_err;
- p->saved_lasterror = current_lasterr;
- }
- /* else: cannot report the error */
- }
- static void restore_errno(void)
- {
- struct cffi_tls_s *p = get_cffi_tls();
- if (p != NULL) {
- SetLastError(p->saved_lasterror);
- errno = p->saved_errno;
- }
- /* else: cannot report the error */
- }
- /************************************************************/
- #if PY_MAJOR_VERSION >= 3
- static PyObject *b_getwinerror(PyObject *self, PyObject *args, PyObject *kwds)
- {
- int err = -1;
- int len;
- WCHAR *s_buf = NULL; /* Free via LocalFree */
- PyObject *v, *message;
- static char *keywords[] = {"code", NULL};
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", keywords, &err))
- return NULL;
- if (err == -1) {
- struct cffi_tls_s *p = get_cffi_tls();
- if (p == NULL)
- return PyErr_NoMemory();
- err = p->saved_lasterror;
- }
- len = FormatMessageW(
- /* Error API error */
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, /* no message source */
- err,
- MAKELANGID(LANG_NEUTRAL,
- SUBLANG_DEFAULT), /* Default language */
- (LPWSTR) &s_buf,
- 0, /* size not used */
- NULL); /* no args */
- if (len==0) {
- /* Only seen this in out of mem situations */
- message = PyUnicode_FromFormat("Windows Error 0x%X", err);
- } else {
- /* remove trailing cr/lf and dots */
- while (len > 0 && (s_buf[len-1] <= L' ' || s_buf[len-1] == L'.'))
- s_buf[--len] = L'\0';
- message = PyUnicode_FromWideChar(s_buf, len);
- }
- if (message != NULL) {
- v = Py_BuildValue("(iO)", err, message);
- Py_DECREF(message);
- }
- else
- v = NULL;
- LocalFree(s_buf);
- return v;
- }
- #else
- static PyObject *b_getwinerror(PyObject *self, PyObject *args, PyObject *kwds)
- {
- int err = -1;
- int len;
- char *s;
- char *s_buf = NULL; /* Free via LocalFree */
- char s_small_buf[40]; /* Room for "Windows Error 0xFFFFFFFFFFFFFFFF" */
- PyObject *v;
- static char *keywords[] = {"code", NULL};
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", keywords, &err))
- return NULL;
- if (err == -1) {
- struct cffi_tls_s *p = get_cffi_tls();
- if (p == NULL)
- return PyErr_NoMemory();
- err = p->saved_lasterror;
- }
- len = FormatMessage(
- /* Error API error */
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, /* no message source */
- err,
- MAKELANGID(LANG_NEUTRAL,
- SUBLANG_DEFAULT), /* Default language */
- (LPTSTR) &s_buf,
- 0, /* size not used */
- NULL); /* no args */
- if (len==0) {
- /* Only seen this in out of mem situations */
- sprintf(s_small_buf, "Windows Error 0x%X", err);
- s = s_small_buf;
- } else {
- s = s_buf;
- /* remove trailing cr/lf and dots */
- while (len > 0 && (s[len-1] <= ' ' || s[len-1] == '.'))
- s[--len] = '\0';
- }
- v = Py_BuildValue("(is)", err, s);
- LocalFree(s_buf);
- return v;
- }
- #endif
- /************************************************************/
- /* Emulate dlopen()&co. from the Windows API */
- #define RTLD_LAZY 0
- #define RTLD_NOW 0
- #define RTLD_GLOBAL 0
- #define RTLD_LOCAL 0
- static void *dlopen(const char *filename, int flag)
- {
- return (void *)LoadLibraryA(filename);
- }
- static void *dlopenW(const wchar_t *filename)
- {
- return (void *)LoadLibraryW(filename);
- }
- static void *dlsym(void *handle, const char *symbol)
- {
- void *address = GetProcAddress((HMODULE)handle, symbol);
- #ifndef MS_WIN64
- if (!address) {
- /* If 'symbol' is not found, then try '_symbol@N' for N in
- (0, 4, 8, 12, ..., 124). Unlike ctypes, we try to do that
- for any symbol, although in theory it should only be done
- for __stdcall functions.
- */
- int i;
- char *mangled_name = alloca(1 + strlen(symbol) + 1 + 3 + 1);
- if (!mangled_name)
- return NULL;
- for (i = 0; i < 32; i++) {
- sprintf(mangled_name, "_%s@%d", symbol, i * 4);
- address = GetProcAddress((HMODULE)handle, mangled_name);
- if (address)
- break;
- }
- }
- #endif
- return address;
- }
- static int dlclose(void *handle)
- {
- return FreeLibrary((HMODULE)handle) ? 0 : -1;
- }
- static const char *dlerror(void)
- {
- static char buf[32];
- DWORD dw = GetLastError();
- if (dw == 0)
- return NULL;
- sprintf(buf, "error 0x%x", (unsigned int)dw);
- return buf;
- }
|