Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
number of tests, all because of the codecs/_multibytecodecs issue described
here (it's not a Py3K issue, just something Py3K discovers):
http://mail.python.org/pipermail/python-dev/2006-April/064051.html

Hye-Shik Chang promised to look for a fix, so no need to fix it here. The
tests that are expected to break are:

test_codecencodings_cn
test_codecencodings_hk
test_codecencodings_jp
test_codecencodings_kr
test_codecencodings_tw
test_codecs
test_multibytecodec

This merge fixes an actual test failure (test_weakref) in this branch,
though, so I believe merging is the right thing to do anyway.
diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c
index 926c85b..e6d6aa4 100644
--- a/Modules/_ctypes/_ctypes.c
+++ b/Modules/_ctypes/_ctypes.c
@@ -105,6 +105,10 @@
 #include <ffi.h>
 #ifdef MS_WIN32
 #include <windows.h>
+#include <malloc.h>
+#ifndef IS_INTRESOURCE
+#define IS_INTRESOURCE(x) (((size_t)(x) >> 16) == 0)
+#endif
 # ifdef _WIN32_WCE
 /* Unlike desktop Windows, WinCE has both W and A variants of
    GetProcAddress, but the default W version is not what we want */
@@ -285,6 +289,7 @@
 	if (PyCArg_CheckExact(value)) {
 		PyCArgObject *p = (PyCArgObject *)value;
 		PyObject *ob = p->obj;
+		const char *ob_name;
 		StgDictObject *dict;
 		dict = PyType_stgdict(type);
 
@@ -296,10 +301,10 @@
 			Py_INCREF(value);
 			return value;
 		}
+		ob_name = (ob) ? ob->ob_type->tp_name : "???";
 		PyErr_Format(PyExc_TypeError,
 			     "expected %s instance instead of pointer to %s",
-			     ((PyTypeObject *)type)->tp_name,
-			     ob->ob_type->tp_name);
+			     ((PyTypeObject *)type)->tp_name, ob_name);
 		return NULL;
 	}
 #if 1
@@ -506,12 +511,12 @@
 static int
 PointerType_SetProto(StgDictObject *stgdict, PyObject *proto)
 {
-	if (proto && !PyType_Check(proto)) {
+	if (!proto || !PyType_Check(proto)) {
 		PyErr_SetString(PyExc_TypeError,
 				"_type_ must be a type");
 		return -1;
 	}
-	if (proto && !PyType_stgdict(proto)) {
+	if (!PyType_stgdict(proto)) {
 		PyErr_SetString(PyExc_TypeError,
 				"_type_ must have storage info");
 		return -1;
@@ -543,8 +548,8 @@
 		return NULL;
 	stgdict->size = sizeof(void *);
 	stgdict->align = getentry("P")->pffi_type->alignment;
-	stgdict->length = 2;
-	stgdict->ffi_type = ffi_type_pointer;
+	stgdict->length = 1;
+	stgdict->ffi_type_pointer = ffi_type_pointer;
 
 	proto = PyDict_GetItemString(typedict, "_type_"); /* Borrowed ref */
 	if (proto && -1 == PointerType_SetProto(stgdict, proto)) {
@@ -899,7 +904,7 @@
 	PyObject *typedict;
 	int length;
 
-	int itemsize, itemalign, itemlen;
+	int itemsize, itemalign;
 
 	typedict = PyTuple_GetItem(args, 2);
 	if (!typedict)
@@ -936,7 +941,6 @@
 
 	itemsize = itemdict->size;
 	itemalign = itemdict->align;
-	itemlen = itemdict->length;
 
 	stgdict->size = itemsize * length;
 	stgdict->align = itemalign;
@@ -945,7 +949,7 @@
 	stgdict->proto = proto;
 
 	/* Arrays are passed as pointers to function calls. */
-	stgdict->ffi_type = ffi_type_pointer;
+	stgdict->ffi_type_pointer = ffi_type_pointer;
 
 	/* create the new instance (which is a class,
 	   since we are a metatype!) */
@@ -1264,9 +1268,13 @@
 	PyTypeObject *result;
 	StgDictObject *stgdict;
 	PyObject *name = PyTuple_GET_ITEM(args, 0);
-	PyObject *swapped_args = PyTuple_New(PyTuple_GET_SIZE(args));
+	PyObject *swapped_args;
 	static PyObject *suffix;
-	int i;
+	Py_ssize_t i;
+
+	swapped_args = PyTuple_New(PyTuple_GET_SIZE(args));
+	if (!swapped_args)
+		return NULL;
 
 	if (suffix == NULL)
 #ifdef WORDS_BIGENDIAN
@@ -1275,8 +1283,10 @@
 		suffix = PyString_FromString("_be");
 #endif
 
-	Py_INCREF(suffix);
-	PyString_ConcatAndDel(&name, suffix);
+	Py_INCREF(name);
+	PyString_Concat(&name, suffix);
+	if (name == NULL)
+		return NULL;
 
 	PyTuple_SET_ITEM(swapped_args, 0, name);
 	for (i=1; i<PyTuple_GET_SIZE(args); ++i) {
@@ -1297,7 +1307,7 @@
 	if (!stgdict) /* XXX leaks result! */
 		return NULL;
 
-	stgdict->ffi_type = *fmt->pffi_type;
+	stgdict->ffi_type_pointer = *fmt->pffi_type;
 	stgdict->align = fmt->pffi_type->alignment;
 	stgdict->length = 0;
 	stgdict->size = fmt->pffi_type->size;
@@ -1355,7 +1365,7 @@
 
 	fmt = getentry(PyString_AS_STRING(proto));
 
-	stgdict->ffi_type = *fmt->pffi_type;
+	stgdict->ffi_type_pointer = *fmt->pffi_type;
 	stgdict->align = fmt->pffi_type->alignment;
 	stgdict->length = 0;
 	stgdict->size = fmt->pffi_type->size;
@@ -1450,6 +1460,7 @@
 		PyObject_SetAttrString(swapped, "__ctype_le__", (PyObject *)result);
 		PyObject_SetAttrString(swapped, "__ctype_be__", swapped);
 #endif
+		Py_DECREF(swapped);
 	};
 
 	return (PyObject *)result;
@@ -1624,7 +1635,7 @@
 	stgdict->size = sizeof(void *);
 	stgdict->setfunc = NULL;
 	stgdict->getfunc = NULL;
-	stgdict->ffi_type = ffi_type_pointer;
+	stgdict->ffi_type_pointer = ffi_type_pointer;
 
 	ob = PyDict_GetItemString((PyObject *)stgdict, "_flags_");
 	if (!ob || !PyInt_Check(ob)) {
@@ -1846,7 +1857,7 @@
 	StgDictObject *dict = PyObject_stgdict((PyObject *)self);
 	Py_CLEAR(self->b_objects);
 	if ((self->b_needsfree)
-	    && (dict->size > sizeof(self->b_value)))
+	    && ((size_t)dict->size > sizeof(self->b_value)))
 		PyMem_Free(self->b_ptr);
 	self->b_ptr = NULL;
 	Py_CLEAR(self->b_base);
@@ -1873,8 +1884,9 @@
 	{ NULL },
 };
 
-static Py_ssize_t CData_GetBuffer(CDataObject *self, Py_ssize_t seg, void **pptr)
+static Py_ssize_t CData_GetBuffer(PyObject *_self, Py_ssize_t seg, void **pptr)
 {
+	CDataObject *self = (CDataObject *)_self;
 	if (seg != 0) {
 		/* Hm. Must this set an exception? */
 		return -1;
@@ -1883,7 +1895,7 @@
 	return self->b_size;
 }
 
-static Py_ssize_t CData_GetSegcount(CDataObject *self, Py_ssize_t *lenp)
+static Py_ssize_t CData_GetSegcount(PyObject *_self, Py_ssize_t *lenp)
 {
 	if (lenp)
 		*lenp = 1;
@@ -1891,10 +1903,10 @@
 }
 
 static PyBufferProcs CData_as_buffer = {
-	(readbufferproc)CData_GetBuffer,
-	(writebufferproc)CData_GetBuffer,
-	(segcountproc)CData_GetSegcount,
-	(charbufferproc)NULL,
+	CData_GetBuffer,
+	CData_GetBuffer,
+	CData_GetSegcount,
+	NULL,
 };
 
 /*
@@ -1967,7 +1979,7 @@
 
 static void CData_MallocBuffer(CDataObject *obj, StgDictObject *dict)
 {
-	if (dict->size <= sizeof(obj->b_value)) {
+	if ((size_t)dict->size <= sizeof(obj->b_value)) {
 		/* No need to call malloc, can use the default buffer */
 		obj->b_ptr = (char *)&obj->b_value;
 		obj->b_needsfree = 1;
@@ -1975,7 +1987,7 @@
 		/* In python 2.4, and ctypes 0.9.6, the malloc call took about
 		   33% of the creation time for c_int().
 		*/
-		obj->b_ptr = PyMem_Malloc(dict->size);
+		obj->b_ptr = (char *)PyMem_Malloc(dict->size);
 		obj->b_needsfree = 1;
 		memset(obj->b_ptr, 0, dict->size);
 	}
@@ -2040,7 +2052,7 @@
 	if (!pd)
 		return NULL;
 	assert(CDataObject_Check(pd));
-	pd->b_ptr = buf;
+	pd->b_ptr = (char *)buf;
 	pd->b_length = dict->length;
 	pd->b_size = dict->size;
 	return (PyObject *)pd;
@@ -2383,6 +2395,11 @@
 	address = (PPROC)GetProcAddress(handle, name);
 	if (address)
 		return address;
+
+	if (((size_t)name & ~0xFFFF) == 0) {
+		return NULL;
+	}
+
 	/* It should not happen that dict is NULL, but better be safe */
 	if (dict==NULL || dict->flags & FUNCFLAG_CDECL)
 		return address;
@@ -2391,7 +2408,7 @@
 	   funcname -> _funcname@<n>
 	   where n is 0, 4, 8, 12, ..., 128
 	 */
-	mangled_name = _alloca(strlen(name) + 1 + 1 + 1 + 3); /* \0 _ @ %d */
+	mangled_name = alloca(strlen(name) + 1 + 1 + 1 + 3); /* \0 _ @ %d */
 	for (i = 0; i < 32; ++i) {
 		sprintf(mangled_name, "_%s@%d", name, i*4);
 		address = (PPROC)GetProcAddress(handle, mangled_name);
@@ -2488,6 +2505,28 @@
 	return 1;
 }
 
+static int
+_get_name(PyObject *obj, char **pname)
+{
+#ifdef MS_WIN32
+	if (PyInt_Check(obj) || PyLong_Check(obj)) {
+		/* We have to use MAKEINTRESOURCEA for Windows CE.
+		   Works on Windows as well, of course.
+		*/
+		*pname = MAKEINTRESOURCEA(PyInt_AsUnsignedLongMask(obj) & 0xFFFF);
+		return 1;
+	}
+#endif
+	if (PyString_Check(obj) || PyUnicode_Check(obj)) {
+		*pname = PyString_AsString(obj);
+		return *pname ? 1 : 0;
+	}
+	PyErr_SetString(PyExc_TypeError,
+			"function name must be string or integer");
+	return 0;
+}
+
+
 static PyObject *
 CFuncPtr_FromDll(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
@@ -2499,7 +2538,7 @@
 	void *handle;
 	PyObject *paramflags = NULL;
 
-	if (!PyArg_ParseTuple(args, "sO|O", &name, &dll, &paramflags))
+	if (!PyArg_ParseTuple(args, "(O&O)|O", _get_name, &name, &dll, &paramflags))
 		return NULL;
 	if (paramflags == Py_None)
 		paramflags = NULL;
@@ -2524,9 +2563,14 @@
 #ifdef MS_WIN32
 	address = FindAddress(handle, name, (PyObject *)type);
 	if (!address) {
-		PyErr_Format(PyExc_AttributeError,
-			     "function '%s' not found",
-			     name);
+		if (!IS_INTRESOURCE(name))
+			PyErr_Format(PyExc_AttributeError,
+				     "function '%s' not found",
+				     name);
+		else
+			PyErr_Format(PyExc_AttributeError,
+				     "function ordinal %d not found",
+				     (WORD)(size_t)name);
 		return NULL;
 	}
 #else
@@ -2603,8 +2647,9 @@
   "O" - must be a callable, creates a C callable function
 
   two or more argument forms (the third argument is a paramflags tuple)
-  "sO|O" - function name, dll object (with an integer handle)
-  "is|O" - vtable index, method name, creates callable calling COM vtbl
+  "(sO)|..." - (function name, dll object (with an integer handle)), paramflags
+  "(iO)|..." - (function ordinal, dll object (with an integer handle)), paramflags
+  "is|..." - vtable index, method name, creates callable calling COM vtbl
 */
 static PyObject *
 CFuncPtr_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
@@ -2612,19 +2657,18 @@
 	CFuncPtrObject *self;
 	PyObject *callable;
 	StgDictObject *dict;
-	THUNK thunk;
+	ffi_info *thunk;
 
 	if (PyTuple_GET_SIZE(args) == 0)
 		return GenericCData_new(type, args, kwds);
 
-	/* Shouldn't the following better be done in __init__? */
-	if (2 <= PyTuple_GET_SIZE(args)) {
-#ifdef MS_WIN32
-		if (PyInt_Check(PyTuple_GET_ITEM(args, 0)))
-			return CFuncPtr_FromVtblIndex(type, args, kwds);
-#endif
+	if (1 <= PyTuple_GET_SIZE(args) && PyTuple_Check(PyTuple_GET_ITEM(args, 0)))
 		return CFuncPtr_FromDll(type, args, kwds);
-	}
+
+#ifdef MS_WIN32
+	if (2 <= PyTuple_GET_SIZE(args) && PyInt_Check(PyTuple_GET_ITEM(args, 0)))
+		return CFuncPtr_FromVtblIndex(type, args, kwds);
+#endif
 
 	if (1 == PyTuple_GET_SIZE(args)
 	    && (PyInt_Check(PyTuple_GET_ITEM(args, 0))
@@ -2781,7 +2825,7 @@
 static PyObject *
 _build_callargs(CFuncPtrObject *self, PyObject *argtypes,
 		PyObject *inargs, PyObject *kwds,
-		int *poutmask, int *pinoutmask, int *pnumretvals)
+		int *poutmask, int *pinoutmask, unsigned int *pnumretvals)
 {
 	PyObject *paramflags = self->paramflags;
 	PyObject *callargs;
@@ -2835,8 +2879,14 @@
 
 		switch (flag & (PARAMFLAG_FIN | PARAMFLAG_FOUT | PARAMFLAG_FLCID)) {
 		case PARAMFLAG_FIN | PARAMFLAG_FLCID:
-			/* ['in', 'lcid'] parameter.  Always taken from defval */
-			Py_INCREF(defval);
+			/* ['in', 'lcid'] parameter.  Always taken from defval,
+			 if given, else the integer 0. */
+			if (defval == NULL) {
+				defval = PyInt_FromLong(0);
+				if (defval == NULL)
+					goto error;
+			} else
+				Py_INCREF(defval);
 			PyTuple_SET_ITEM(callargs, i, defval);
 			break;
 		case (PARAMFLAG_FIN | PARAMFLAG_FOUT):
@@ -2939,9 +2989,10 @@
 */
 static PyObject *
 _build_result(PyObject *result, PyObject *callargs,
-	      int outmask, int inoutmask, int numretvals)
+	      int outmask, int inoutmask, unsigned int numretvals)
 {
-	int i, index, bit;
+	unsigned int i, index;
+	int bit;
 	PyObject *tup = NULL;
 
 	if (callargs == NULL)
@@ -2952,6 +3003,7 @@
 	}
 	Py_DECREF(result);
 
+	/* tup will not be allocated if numretvals == 1 */
 	/* allocate tuple to hold the result */
 	if (numretvals > 1) {
 		tup = PyTuple_New(numretvals);
@@ -3009,7 +3061,7 @@
 
 	int inoutmask;
 	int outmask;
-	int numretvals;
+	unsigned int numretvals;
 
 	assert(dict); /* if not, it's a bug */
 	restype = self->restype ? self->restype : dict->restype;
@@ -3145,9 +3197,11 @@
 	Py_CLEAR(self->converters);
 	Py_CLEAR(self->paramflags);
 
-	if (self->thunk)
-		FreeCallback(self->thunk);
-	self->thunk = NULL;
+	if (self->thunk) {
+		FreeClosure(self->thunk->pcl);
+		PyMem_Free(self->thunk);
+		self->thunk = NULL;
+	}
 
 	return CData_clear((CDataObject *)self);
 }
@@ -3241,7 +3295,7 @@
 
 	parg->tag = 'V';
 	stgdict = PyObject_stgdict((PyObject *)self);
-	parg->pffi_type = &stgdict->ffi_type;
+	parg->pffi_type = &stgdict->ffi_type_pointer;
 	/* For structure parameters (by value), parg->value doesn't contain the structure
 	   data itself, instead parg->value.p *points* to the structure's data
 	   See also _ctypes.c, function _call_function_pointer().
@@ -3275,6 +3329,8 @@
 		if (!fields) {
 			PyErr_Clear();
 			fields = PyTuple_New(0);
+			if (!fields)
+				return -1;
 		}
 
 		if (PyTuple_GET_SIZE(args) > PySequence_Length(fields)) {
@@ -3445,8 +3501,9 @@
 }
 
 static PyObject *
-Array_item(CDataObject *self, int index)
+Array_item(PyObject *_self, Py_ssize_t index)
 {
+	CDataObject *self = (CDataObject *)_self;
 	int offset, size;
 	StgDictObject *stgdict;
 
@@ -3469,8 +3526,9 @@
 }
 
 static PyObject *
-Array_slice(CDataObject *self, Py_ssize_t ilow, Py_ssize_t ihigh)
+Array_slice(PyObject *_self, Py_ssize_t ilow, Py_ssize_t ihigh)
 {
+	CDataObject *self = (CDataObject *)_self;
 	StgDictObject *stgdict, *itemdict;
 	PyObject *proto;
 	PyListObject *np;
@@ -3504,15 +3562,16 @@
 		return NULL;
 
 	for (i = 0; i < len; i++) {
-		PyObject *v = Array_item(self, i+ilow);
+		PyObject *v = Array_item(_self, i+ilow);
 		PyList_SET_ITEM(np, i, v);
 	}
 	return (PyObject *)np;
 }
 
 static int
-Array_ass_item(CDataObject *self, int index, PyObject *value)
+Array_ass_item(PyObject *_self, Py_ssize_t index, PyObject *value)
 {
+	CDataObject *self = (CDataObject *)_self;
 	int size, offset;
 	StgDictObject *stgdict;
 	char *ptr;
@@ -3538,8 +3597,9 @@
 }
 
 static int
-Array_ass_slice(CDataObject *self, int ilow, int ihigh, PyObject *value)
+Array_ass_slice(PyObject *_self, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject *value)
 {
+	CDataObject *self = (CDataObject *)_self;
 	int i, len;
 
 	if (value == NULL) {
@@ -3570,7 +3630,7 @@
 		int result;
 		if (item == NULL)
 			return -1;
-		result = Array_ass_item(self, i+ilow, item);
+		result = Array_ass_item(_self, i+ilow, item);
 		Py_DECREF(item);
 		if (result == -1)
 			return -1;
@@ -3578,20 +3638,21 @@
 	return 0;
 }
 
-static int
-Array_length(CDataObject *self)
+static Py_ssize_t
+Array_length(PyObject *_self)
 {
+	CDataObject *self = (CDataObject *)_self;
 	return self->b_length;
 }
 
 static PySequenceMethods Array_as_sequence = {
-	(lenfunc)Array_length,			/* sq_length; */
+	Array_length,				/* sq_length; */
 	0,					/* sq_concat; */
 	0,					/* sq_repeat; */
-	(ssizeargfunc)Array_item,		/* sq_item; */
-	(ssizessizeargfunc)Array_slice,		/* sq_slice; */
-	(ssizeobjargproc)Array_ass_item,	/* sq_ass_item; */
-	(ssizessizeobjargproc)Array_ass_slice,	/* sq_ass_slice; */
+	Array_item,				/* sq_item; */
+	Array_slice,				/* sq_slice; */
+	Array_ass_item,				/* sq_ass_item; */
+	Array_ass_slice,			/* sq_ass_slice; */
 	0,					/* sq_contains; */
 	
 	0,					/* sq_inplace_concat; */
@@ -3942,8 +4003,9 @@
   Pointer_Type
 */
 static PyObject *
-Pointer_item(CDataObject *self, int index)
+Pointer_item(PyObject *_self, Py_ssize_t index)
 {
+	CDataObject *self = (CDataObject *)_self;
 	int size, offset;
 	StgDictObject *stgdict, *itemdict;
 	PyObject *proto;
@@ -3969,8 +4031,9 @@
 }
 
 static int
-Pointer_ass_item(CDataObject *self, int index, PyObject *value)
+Pointer_ass_item(PyObject *_self, Py_ssize_t index, PyObject *value)
 {
+	CDataObject *self = (CDataObject *)_self;
 	int size;
 	StgDictObject *stgdict;
 
@@ -4111,8 +4174,9 @@
 }
 
 static PyObject *
-Pointer_slice(CDataObject *self, Py_ssize_t ilow, Py_ssize_t ihigh)
+Pointer_slice(PyObject *_self, Py_ssize_t ilow, Py_ssize_t ihigh)
 {
+	CDataObject *self = (CDataObject *)_self;
 	PyListObject *np;
 	StgDictObject *stgdict, *itemdict;
 	PyObject *proto;
@@ -4142,7 +4206,7 @@
 		return NULL;
 
 	for (i = 0; i < len; i++) {
-		PyObject *v = Pointer_item(self, i+ilow);
+		PyObject *v = Pointer_item(_self, i+ilow);
 		PyList_SET_ITEM(np, i, v);
 	}
 	return (PyObject *)np;
@@ -4152,9 +4216,9 @@
 	0,					/* inquiry sq_length; */
 	0,					/* binaryfunc sq_concat; */
 	0,					/* intargfunc sq_repeat; */
-	(ssizeargfunc)Pointer_item,		/* intargfunc sq_item; */
-	(ssizessizeargfunc)Pointer_slice,	/* intintargfunc sq_slice; */
-	(ssizeobjargproc)Pointer_ass_item,	/* intobjargproc sq_ass_item; */
+	Pointer_item,				/* intargfunc sq_item; */
+	Pointer_slice,				/* intintargfunc sq_slice; */
+	Pointer_ass_item,			/* intobjargproc sq_ass_item; */
 	0,					/* intintobjargproc sq_ass_slice; */
 	0,					/* objobjproc sq_contains; */
 	/* Added in release 2.0 */
@@ -4334,6 +4398,42 @@
 	return PyString_FromStringAndSize(ptr, size);
 }
 
+static int
+cast_check_pointertype(PyObject *arg)
+{
+	StgDictObject *dict;
+
+	if (PointerTypeObject_Check(arg))
+		return 1;
+	dict = PyType_stgdict(arg);
+	if (dict) {
+		if (PyString_Check(dict->proto)
+		    && (strchr("sPzUZXO", PyString_AS_STRING(dict->proto)[0]))) {
+			/* simple pointer types, c_void_p, c_wchar_p, BSTR, ... */
+			return 1;
+		}
+	}
+	PyErr_Format(PyExc_TypeError,
+		     "cast() argument 2 must be a pointer type, not %s",
+		     PyType_Check(arg)
+		     ? ((PyTypeObject *)arg)->tp_name
+		     : arg->ob_type->tp_name);
+	return 0;
+}
+
+static PyObject *
+cast(void *ptr, PyObject *ctype)
+{
+	CDataObject *result;
+	if (0 == cast_check_pointertype(ctype))
+		return NULL;
+	result = (CDataObject *)PyObject_CallFunctionObjArgs(ctype, NULL);
+	if (result == NULL)
+		return NULL;
+	/* Should we assert that result is a pointer type? */
+	memcpy(result->b_ptr, &ptr, sizeof(void *));
+	return (PyObject *)result;
+}
 
 #ifdef CTYPES_UNICODE
 static PyObject *
@@ -4469,14 +4569,25 @@
 	PyModule_AddObject(m, "_memmove_addr", PyLong_FromVoidPtr(memmove));
 	PyModule_AddObject(m, "_memset_addr", PyLong_FromVoidPtr(memset));
 	PyModule_AddObject(m, "_string_at_addr", PyLong_FromVoidPtr(string_at));
+	PyModule_AddObject(m, "_cast_addr", PyLong_FromVoidPtr(cast));
 #ifdef CTYPES_UNICODE
 	PyModule_AddObject(m, "_wstring_at_addr", PyLong_FromVoidPtr(wstring_at));
 #endif
 
-#ifdef RTLD_LOCAL
+/* If RTLD_LOCAL is not defined (Windows!), set it to zero. */
+#ifndef RTLD_LOCAL
+#define RTLD_LOCAL 0
+#endif
+
+/* If RTLD_GLOBAL is not defined (cygwin), set it to the same value as
+   RTLD_LOCAL.
+*/
+#ifndef RTLD_GLOBAL
+#define RTLD_GLOBAL RTLD_LOCAL
+#endif
+
 	PyModule_AddObject(m, "RTLD_LOCAL", PyInt_FromLong(RTLD_LOCAL));
 	PyModule_AddObject(m, "RTLD_GLOBAL", PyInt_FromLong(RTLD_GLOBAL));
-#endif
 	
 	PyExc_ArgError = PyErr_NewException("ctypes.ArgumentError", NULL, NULL);
 	if (PyExc_ArgError) {