Patch #1075: Use wide API to format error messages.

This commit is contained in:
Martin v. Löwis 2007-09-03 07:40:24 +00:00
parent c76473d887
commit 5d12abe0b1
1 changed files with 57 additions and 32 deletions

View File

@ -10,8 +10,8 @@ extern char *strerror(int);
#endif #endif
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
#include "windows.h" #include <windows.h>
#include "winbase.h" #include <winbase.h>
#endif #endif
#include <ctype.h> #include <ctype.h>
@ -270,30 +270,38 @@ PyErr_NoMemory(void)
PyObject * PyObject *
PyErr_SetFromErrnoWithFilenameObject(PyObject *exc, PyObject *filenameObject) PyErr_SetFromErrnoWithFilenameObject(PyObject *exc, PyObject *filenameObject)
{ {
PyObject *message;
PyObject *v; PyObject *v;
char *s;
int i = errno; int i = errno;
#ifdef PLAN9 #ifdef PLAN9
char errbuf[ERRMAX]; char errbuf[ERRMAX];
#endif #else
#ifdef MS_WINDOWS #ifndef MS_WINDOWS
char *s_buf = NULL; char *s;
char s_small_buf[28]; /* Room for "Windows Error 0xFFFFFFFF" */ #else
#endif WCHAR *s_buf = NULL;
#endif /* Unix/Windows */
#endif /* PLAN 9*/
#ifdef EINTR #ifdef EINTR
if (i == EINTR && PyErr_CheckSignals()) if (i == EINTR && PyErr_CheckSignals())
return NULL; return NULL;
#endif #endif
#ifdef PLAN9 #ifdef PLAN9
rerrstr(errbuf, sizeof errbuf); rerrstr(errbuf, sizeof errbuf);
s = errbuf; message = PyUnicode_DecodeUTF8(errbuf, strlen(errbuf), "ignore");
#else #else
#ifndef MS_WINDOWS
if (i == 0) if (i == 0)
s = "Error"; /* Sometimes errno didn't get set */ s = "Error"; /* Sometimes errno didn't get set */
else else
#ifndef MS_WINDOWS
s = strerror(i); s = strerror(i);
message = PyUnicode_DecodeUTF8(s, strlen(s), "ignore");
#else #else
if (i == 0)
message = PyUnicode_FromString("Error"); /* Sometimes errno didn't get set */
else
{ {
/* Note that the Win32 errors do not lineup with the /* Note that the Win32 errors do not lineup with the
errno error. So if the error is in the MSVC error errno error. So if the error is in the MSVC error
@ -301,10 +309,10 @@ PyErr_SetFromErrnoWithFilenameObject(PyObject *exc, PyObject *filenameObject)
a Win32 error code a Win32 error code
*/ */
if (i > 0 && i < _sys_nerr) { if (i > 0 && i < _sys_nerr) {
s = _sys_errlist[i]; message = PyUnicode_FromString(_sys_errlist[i]);
} }
else { else {
int len = FormatMessage( int len = FormatMessageW(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, FORMAT_MESSAGE_IGNORE_INSERTS,
@ -313,29 +321,39 @@ PyErr_SetFromErrnoWithFilenameObject(PyObject *exc, PyObject *filenameObject)
MAKELANGID(LANG_NEUTRAL, MAKELANGID(LANG_NEUTRAL,
SUBLANG_DEFAULT), SUBLANG_DEFAULT),
/* Default language */ /* Default language */
(LPTSTR) &s_buf, (LPWSTR) &s_buf,
0, /* size not used */ 0, /* size not used */
NULL); /* no args */ NULL); /* no args */
if (len==0) { if (len==0) {
/* Only ever seen this in out-of-mem /* Only ever seen this in out-of-mem
situations */ situations */
sprintf(s_small_buf, "Windows Error 0x%X", i);
s = s_small_buf;
s_buf = NULL; s_buf = NULL;
message = PyUnicode_FromFormat("Windows Error 0x%X", i);
} else { } else {
s = s_buf;
/* remove trailing cr/lf and dots */ /* remove trailing cr/lf and dots */
while (len > 0 && (s[len-1] <= ' ' || s[len-1] == '.')) while (len > 0 && (s_buf[len-1] <= L' ' || s_buf[len-1] == L'.'))
s[--len] = '\0'; s_buf[--len] = L'\0';
message = PyUnicode_FromUnicode(s_buf, len);
} }
} }
} }
#endif /* Unix/Windows */ #endif /* Unix/Windows */
#endif /* PLAN 9*/ #endif /* PLAN 9*/
if (message == NULL)
{
#ifdef MS_WINDOWS
LocalFree(s_buf);
#endif
return NULL;
}
if (filenameObject != NULL) if (filenameObject != NULL)
v = Py_BuildValue("(iUO)", i, s, filenameObject); v = Py_BuildValue("(iOO)", i, message, filenameObject);
else else
v = Py_BuildValue("(iU)", i, s); v = Py_BuildValue("(iO)", i, message);
Py_DECREF(message);
if (v != NULL) { if (v != NULL) {
PyErr_SetObject(exc, v); PyErr_SetObject(exc, v);
Py_DECREF(v); Py_DECREF(v);
@ -383,13 +401,12 @@ PyObject *PyErr_SetExcFromWindowsErrWithFilenameObject(
PyObject *filenameObject) PyObject *filenameObject)
{ {
int len; int len;
char *s; WCHAR *s_buf = NULL; /* Free via LocalFree */
char *s_buf = NULL; /* Free via LocalFree */ PyObject *message;
char s_small_buf[28]; /* Room for "Windows Error 0xFFFFFFFF" */
PyObject *v; PyObject *v;
DWORD err = (DWORD)ierr; DWORD err = (DWORD)ierr;
if (err==0) err = GetLastError(); if (err==0) err = GetLastError();
len = FormatMessage( len = FormatMessageW(
/* Error API error */ /* Error API error */
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_SYSTEM |
@ -398,24 +415,32 @@ PyObject *PyErr_SetExcFromWindowsErrWithFilenameObject(
err, err,
MAKELANGID(LANG_NEUTRAL, MAKELANGID(LANG_NEUTRAL,
SUBLANG_DEFAULT), /* Default language */ SUBLANG_DEFAULT), /* Default language */
(LPTSTR) &s_buf, (LPWSTR) &s_buf,
0, /* size not used */ 0, /* size not used */
NULL); /* no args */ NULL); /* no args */
if (len==0) { if (len==0) {
/* Only seen this in out of mem situations */ /* Only seen this in out of mem situations */
sprintf(s_small_buf, "Windows Error 0x%X", err); message = PyUnicode_FromFormat("Windows Error 0x%X", err);
s = s_small_buf;
s_buf = NULL; s_buf = NULL;
} else { } else {
s = s_buf;
/* remove trailing cr/lf and dots */ /* remove trailing cr/lf and dots */
while (len > 0 && (s[len-1] <= ' ' || s[len-1] == '.')) while (len > 0 && (s_buf[len-1] <= L' ' || s_buf[len-1] == L'.'))
s[--len] = '\0'; s_buf[--len] = L'\0';
message = PyUnicode_FromUnicode(s_buf, len);
} }
if (message == NULL)
{
LocalFree(s_buf);
return NULL;
}
if (filenameObject != NULL) if (filenameObject != NULL)
v = Py_BuildValue("(iUO)", err, s, filenameObject); v = Py_BuildValue("(iOO)", err, message, filenameObject);
else else
v = Py_BuildValue("(iU)", err, s); v = Py_BuildValue("(iO)", err, message);
Py_DECREF(message);
if (v != NULL) { if (v != NULL) {
PyErr_SetObject(exc, v); PyErr_SetObject(exc, v);
Py_DECREF(v); Py_DECREF(v);