You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
242 lines
6.2 KiB
242 lines
6.2 KiB
#include <malloc.h> /* for alloca() */
|
|
|
|
|
|
/************************************************************/
|
|
/* errno and GetLastError support */
|
|
|
|
#include "misc_thread_common.h"
|
|
|
|
static DWORD cffi_tls_index = TLS_OUT_OF_INDEXES;
|
|
|
|
BOOL WINAPI DllMain(HINSTANCE hinstDLL,
|
|
DWORD reason_for_call,
|
|
LPVOID reserved)
|
|
{
|
|
LPVOID p;
|
|
|
|
switch (reason_for_call) {
|
|
|
|
case DLL_THREAD_DETACH:
|
|
if (cffi_tls_index != TLS_OUT_OF_INDEXES) {
|
|
p = TlsGetValue(cffi_tls_index);
|
|
if (p != NULL) {
|
|
TlsSetValue(cffi_tls_index, NULL);
|
|
cffi_thread_shutdown(p);
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
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);
|
|
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;
|
|
s_buf = NULL;
|
|
} 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;
|
|
}
|