1 // 2 // Error.cpp 3 // 4 // Library: Foundation 5 // Package: Core 6 // Module: Error 7 // 8 // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. 9 // and Contributors. 10 // 11 // SPDX-License-Identifier: BSL-1.0 12 // 13 14 15 #include "Poco/Foundation.h" 16 #include "Poco/UnicodeConverter.h" 17 #include "Poco/Error.h" 18 #include <string> 19 #include <string.h> 20 #include <errno.h> 21 22 23 namespace Poco { 24 25 26 #ifdef POCO_OS_FAMILY_WINDOWS 27 28 last()29 DWORD Error::last() 30 { 31 return GetLastError(); 32 } 33 34 getMessage(DWORD errorCode)35 std::string Error::getMessage(DWORD errorCode) 36 { 37 std::string errMsg; 38 DWORD dwFlg = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS; 39 LPWSTR lpMsgBuf = 0; 40 if (FormatMessageW(dwFlg, 0, errorCode, 0, (LPWSTR) & lpMsgBuf, 0, NULL)) 41 UnicodeConverter::toUTF8(lpMsgBuf, errMsg); 42 LocalFree(lpMsgBuf); 43 return errMsg; 44 } 45 46 47 #else 48 49 50 int Error::last() 51 { 52 return errno; 53 } 54 55 56 class StrErrorHelper 57 /// This little hack magically handles all variants 58 /// of strerror_r() (POSIX and GLIBC) and strerror(). 59 { 60 public: 61 explicit StrErrorHelper(int err) 62 { 63 _buffer[0] = 0; 64 65 #if (_XOPEN_SOURCE >= 600) || POCO_OS == POCO_OS_ANDROID || __APPLE__ 66 setMessage(strerror_r(err, _buffer, sizeof(_buffer))); 67 #elif _GNU_SOURCE 68 setMessage(strerror_r(err, _buffer, sizeof(_buffer))); 69 #else 70 setMessage(strerror(err)); 71 #endif 72 } 73 74 ~StrErrorHelper() 75 { 76 } 77 78 const std::string& message() const 79 { 80 return _message; 81 } 82 83 protected: 84 void setMessage(int rc) 85 /// Handles POSIX variant 86 { 87 _message = _buffer; 88 } 89 90 void setMessage(const char* msg) 91 /// Handles GLIBC variant 92 { 93 _message = msg; 94 } 95 96 private: 97 char _buffer[256]; 98 std::string _message; 99 }; 100 101 std::string Error::getMessage(int errorCode) 102 { 103 StrErrorHelper helper(errorCode); 104 return helper.message(); 105 } 106 107 108 #endif 109 110 111 } // namespace Poco 112