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