From 795e189d28f7afd9f4e864a998658e3302efb59e Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Thu, 17 Feb 2000 15:19:15 +0000 Subject: [PATCH] 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. --- Python/errors.c | 90 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 75 insertions(+), 15 deletions(-) diff --git a/Python/errors.c b/Python/errors.c index cb0503b402f..71e51c30233 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -289,6 +289,9 @@ PyErr_SetFromErrnoWithFilename(exc, filename) 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 @@ PyErr_SetFromErrnoWithFilename(exc, filename) 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 @@ PyErr_SetFromErrnoWithFilename(exc, filename) Py_DECREF(v); } #ifdef MS_WIN32 - LocalFree(s); + LocalFree(s_buf); #endif return NULL; } @@ -338,6 +353,51 @@ PyErr_SetFromErrno(exc) 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() {