Merge pull request #285 from mwinterb/winerror_winu

Changed format_windows_error to not need LocalFree
This commit is contained in:
Victor Zverovich 2016-03-06 06:55:37 -08:00
commit 6883d6e724
2 changed files with 38 additions and 19 deletions

View File

@ -588,27 +588,25 @@ FMT_FUNC void fmt::WindowsError::init(
FMT_FUNC void fmt::internal::format_windows_error( FMT_FUNC void fmt::internal::format_windows_error(
fmt::Writer &out, int error_code, fmt::Writer &out, int error_code,
fmt::StringRef message) FMT_NOEXCEPT { fmt::StringRef message) FMT_NOEXCEPT {
class String {
private:
LPWSTR str_;
public:
String() : str_() {}
~String() { LocalFree(str_); }
LPWSTR *ptr() { return &str_; }
LPCWSTR c_str() const { return str_; }
};
FMT_TRY { FMT_TRY {
String system_message; MemoryBuffer<wchar_t, INLINE_BUFFER_SIZE> buffer;
if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | buffer.resize(INLINE_BUFFER_SIZE);
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, for (;;) {
error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), wchar_t *system_message = &buffer[0];
reinterpret_cast<LPWSTR>(system_message.ptr()), 0, 0)) { int result = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
0, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
system_message, static_cast<uint32_t>(buffer.size()), 0);
if (result != 0) {
UTF16ToUTF8 utf8_message; UTF16ToUTF8 utf8_message;
if (utf8_message.convert(system_message.c_str()) == ERROR_SUCCESS) { if (utf8_message.convert(system_message) == ERROR_SUCCESS) {
out << message << ": " << utf8_message; out << message << ": " << utf8_message;
return; return;
} }
break;
}
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
break; // Can't get error message, report error code instead.
buffer.resize(buffer.size() * 2);
} }
} FMT_CATCH(...) {} } FMT_CATCH(...) {}
fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32. fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32.

View File

@ -873,6 +873,27 @@ TEST(UtilTest, FormatWindowsError) {
EXPECT_EQ(fmt::format("error {}", ERROR_FILE_EXISTS), actual_message.str()); EXPECT_EQ(fmt::format("error {}", ERROR_FILE_EXISTS), actual_message.str());
} }
TEST(UtilTest, FormatLongWindowsError) {
LPWSTR message = 0;
// this error code is not available on all Windows platforms and
// Windows SDKs, so do not fail the test if the error string cannot
// be retrieved.
const int provisioning_not_allowed = 0x80284013L /*TBS_E_PROVISIONING_NOT_ALLOWED*/;
if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0,
provisioning_not_allowed, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
reinterpret_cast<LPWSTR>(&message), 0, 0) == 0) {
return;
}
fmt::internal::UTF16ToUTF8 utf8_message(message);
LocalFree(message);
fmt::MemoryWriter actual_message;
fmt::internal::format_windows_error(
actual_message, provisioning_not_allowed, "test");
EXPECT_EQ(fmt::format("test: {}", utf8_message.str()),
actual_message.str());
}
TEST(UtilTest, WindowsError) { TEST(UtilTest, WindowsError) {
check_throw_error<fmt::WindowsError>( check_throw_error<fmt::WindowsError>(
ERROR_FILE_EXISTS, fmt::internal::format_windows_error); ERROR_FILE_EXISTS, fmt::internal::format_windows_error);