Patch by Mark Hammond:

* Changes to a recent patch by Chris Tismer to errors.c.  Chris' patch
always used FormatMessage() to get the error message passing the error code
from errno - but errno and FormatMessage use a different numbering scheme.
The main reason the patch looked OK was that ENOFILE==ERROR_FILE_NOT_FOUND -
but that is about the only shared error code :-).  The MS CRT docs tell you
to use _sys_errlist()/_sys_nerr.  My patch does also this, and adds a very
similar function specifically for win32 error codes.
diff --git a/Python/errors.c b/Python/errors.c
index cb0503b..71e51c3 100644
--- a/Python/errors.c
+++ b/Python/errors.c
@@ -289,6 +289,9 @@
 	PyObject *v;
 	char *s;
 	int i = errno;
+#ifdef MS_WIN32
+	char *s_buf = NULL;
+#endif
 #ifdef EINTR
 	if (i == EINTR && PyErr_CheckSignals())
 		return NULL;
@@ -300,20 +303,32 @@
 		s = strerror(i);
 #else
 	{
-		int len = FormatMessage(
-			FORMAT_MESSAGE_ALLOCATE_BUFFER |
-			FORMAT_MESSAGE_FROM_SYSTEM |
-			FORMAT_MESSAGE_IGNORE_INSERTS,
-			NULL,	/* no message source */
-			i,
-			MAKELANGID(LANG_NEUTRAL,
-				   SUBLANG_DEFAULT), /* Default language */
-			(LPTSTR) &s,
-			0,	/* size not used */
-			NULL);	/* no args */
-		/* remove trailing cr/lf and dots */
-		while (len > 0 && s[len-1] <= '.')
-			s[--len] = '\0';
+		/* Note that the Win32 errors do not lineup with the
+		   errno error.  So if the error is in the MSVC error
+		   table, we use it, otherwise we assume it really _is_ 
+		   a Win32 error code
+		*/
+		if (i < _sys_nerr) {
+			s = _sys_errlist[i];
+		}
+		else {
+			int len = FormatMessage(
+				FORMAT_MESSAGE_ALLOCATE_BUFFER |
+				FORMAT_MESSAGE_FROM_SYSTEM |
+				FORMAT_MESSAGE_IGNORE_INSERTS,
+				NULL,	/* no message source */
+				i,
+				MAKELANGID(LANG_NEUTRAL,
+					   SUBLANG_DEFAULT),
+				           /* Default language */
+				(LPTSTR) &s_buf,
+				0,	/* size not used */
+				NULL);	/* no args */
+			s = s_buf;
+			/* remove trailing cr/lf and dots */
+			while (len > 0 && (s[len-1] <= ' ' || s[len-1] == '.'))
+				s[--len] = '\0';
+		}
 	}
 #endif
 	if (filename != NULL && Py_UseClassExceptionsFlag)
@@ -325,7 +340,7 @@
 		Py_DECREF(v);
 	}
 #ifdef MS_WIN32
-	LocalFree(s);
+	LocalFree(s_buf);
 #endif
 	return NULL;
 }
@@ -338,6 +353,51 @@
 	return PyErr_SetFromErrnoWithFilename(exc, NULL);
 }
 
+#ifdef MS_WINDOWS 
+/* Windows specific error code handling */
+PyObject *PyErr_SetFromWindowsErrWithFilename(
+	int ierr, 
+	const char *filename)
+{
+	int len;
+	char *s;
+	PyObject *v;
+	DWORD err = (DWORD)ierr;
+	if (err==0) err = GetLastError();
+	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,
+		0,	/* size not used */
+		NULL);	/* no args */
+	/* remove trailing cr/lf and dots */
+	while (len > 0 && (s[len-1] <= ' ' || s[len-1] == '.'))
+		s[--len] = '\0';
+	if (filename != NULL && Py_UseClassExceptionsFlag)
+		v = Py_BuildValue("(iss)", err, s, filename);
+	else
+		v = Py_BuildValue("(is)", err, s);
+	if (v != NULL) {
+		PyErr_SetObject(PyExc_EnvironmentError, v);
+		Py_DECREF(v);
+	}
+	LocalFree(s);
+	return NULL;
+}
+
+PyObject *PyErr_SetFromWindowsErr(int ierr)
+{
+	return PyErr_SetFromWindowsErrWithFilename(ierr, NULL);
+
+}
+#endif /* MS_WINDOWS */
+
 void
 PyErr_BadInternalCall()
 {