summaryrefslogtreecommitdiff
path: root/c/misc_win32.h
diff options
context:
space:
mode:
Diffstat (limited to 'c/misc_win32.h')
-rw-r--r--c/misc_win32.h241
1 files changed, 241 insertions, 0 deletions
diff --git a/c/misc_win32.h b/c/misc_win32.h
new file mode 100644
index 0000000..07b76c1
--- /dev/null
+++ b/c/misc_win32.h
@@ -0,0 +1,241 @@
+#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;
+}