[pypy-commit] pypy default: Add FormatMessageW() to get the errors in unicode

arigo pypy.commits at gmail.com
Mon Dec 18 07:43:51 EST 2017


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r93466:d5ba3ff15b4c
Date: 2017-12-18 13:12 +0100
http://bitbucket.org/pypy/pypy/changeset/d5ba3ff15b4c/

Log:	Add FormatMessageW() to get the errors in unicode

diff --git a/rpython/rlib/rwin32.py b/rpython/rlib/rwin32.py
--- a/rpython/rlib/rwin32.py
+++ b/rpython/rlib/rwin32.py
@@ -210,6 +210,10 @@
         'FormatMessageA',
         [DWORD, rffi.VOIDP, DWORD, DWORD, rffi.CCHARP, DWORD, rffi.VOIDP],
         DWORD)
+    FormatMessageW = winexternal(
+        'FormatMessageW',
+        [DWORD, rffi.VOIDP, DWORD, DWORD, rffi.CWCHARP, DWORD, rffi.VOIDP],
+        DWORD)
 
     _get_osfhandle = rffi.llexternal('_get_osfhandle', [rffi.INT], HANDLE)
 
@@ -286,6 +290,8 @@
     # A bit like strerror...
     def FormatError(code):
         return llimpl_FormatError(code)
+    def FormatErrorW(code):
+        return llimpl_FormatErrorW(code)
 
     def llimpl_FormatError(code):
         "Return a message corresponding to the given Windows error code."
@@ -318,6 +324,37 @@
 
         return result
 
+    def llimpl_FormatErrorW(code):
+        "Return a unicode message corresponding to the given Windows error code."
+        buf = lltype.malloc(rffi.CWCHARPP.TO, 1, flavor='raw')
+        buf[0] = lltype.nullptr(rffi.CWCHARP.TO)
+        try:
+            msglen = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+                                    FORMAT_MESSAGE_FROM_SYSTEM | 
+                                    FORMAT_MESSAGE_IGNORE_INSERTS,
+                                    None,
+                                    rffi.cast(DWORD, code),
+                                    DEFAULT_LANGUAGE,
+                                    rffi.cast(rffi.CWCHARP, buf),
+                                    0, None)
+            buflen = intmask(msglen)
+
+            # remove trailing cr/lf and dots
+            s_buf = buf[0]
+            while buflen > 0 and (ord(s_buf[buflen - 1]) <= ord(' ') or
+                                  s_buf[buflen - 1] == u'.'):
+                buflen -= 1
+
+            if buflen <= 0:
+                result = u'Windows Error %d' % (code,)
+            else:
+                result = rffi.wcharpsize2unicode(s_buf, buflen)
+        finally:
+            LocalFree(rffi.cast(rffi.VOIDP, buf[0]))
+            lltype.free(buf, flavor='raw')
+
+        return result
+
     def lastSavedWindowsError(context="Windows Error"):
         code = GetLastError_saved()
         return WindowsError(code, context)
diff --git a/rpython/rlib/test/test_rwin32.py b/rpython/rlib/test/test_rwin32.py
--- a/rpython/rlib/test/test_rwin32.py
+++ b/rpython/rlib/test/test_rwin32.py
@@ -64,3 +64,7 @@
     msg = rwin32.FormatError(34)
     assert '%2' in msg
 
+def test_formaterror_unicode():
+    msg = rwin32.FormatErrorW(34)
+    assert type(msg) is unicode
+    assert u'%2' in msg
diff --git a/rpython/rtyper/lltypesystem/rffi.py b/rpython/rtyper/lltypesystem/rffi.py
--- a/rpython/rtyper/lltypesystem/rffi.py
+++ b/rpython/rtyper/lltypesystem/rffi.py
@@ -1011,6 +1011,7 @@
 
 # char**
 CCHARPP = lltype.Ptr(lltype.Array(CCHARP, hints={'nolength': True}))
+CWCHARPP = lltype.Ptr(lltype.Array(CWCHARP, hints={'nolength': True}))
 
 def liststr2charpp(l):
     """ list[str] -> char**, NULL terminated


More information about the pypy-commit mailing list