18

If I call a Win32 function that reports errors via GetLastError, for example RegisterClassEx, how do I throw a std::system_error for that error?

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
Michael Marcin
  • 686
  • 6
  • 17

2 Answers2

20

Check on the value of GetLastError() like

DWORD dwErrVal = GetLastError();
std::error_code ec (dwErrVal, std::system_category());
throw std::system_error(ec, "Exception occurred");

See here for error_code and here for std::system_error.

bash.d
  • 13,029
  • 3
  • 29
  • 42
  • Is it generic_category? Looking at the vc11 implementation it looks like maybe it should be system_category. – Michael Marcin Apr 06 '13 at 20:09
  • Thank you, didn't know it existed! – bash.d Apr 06 '13 at 20:13
  • Hmm, this doesn't seem to be working for me. GetLastError() is returning ERROR_INVALID_PARAMETER, but the system_error::what simply says "unknown error" – Mooing Duck May 28 '15 at 22:15
  • system_error is for errno codes, not Win32 codes. They're different. http://newscentral.exsees.com/item/d33ca604e6a55888937840570a5cd17d-76c1546f7ca7c2c00921bccdb34ec2d1 – Mooing Duck May 28 '15 at 22:28
  • @MooingDuck I think msvc's system_category implementation *is* meant for codes returned by GetLastError() but it only returns a proper message for a small subset of all codes - at least for VS2013 - and ERROR_INVALID_PARAMETER is not one of them. See _Winerror_map in syserror.cpp in the crt source code.. – stijn Jan 11 '16 at 20:51
  • 1
    The whole `std::system_category()` thing in C++11 is a disaster when it comes to implementing on Win32 platform. Check **[this](http://stackoverflow.com/questions/28746372/system-error-categories-and-standard-system-error-codes)** out. There is basically no provision in the standard for systems which have *both* `errno` *and* native error codes. – rustyx Jun 03 '16 at 09:19
  • @stijn AFAIK, syserror.cpp only defines Windows to POSIX mapping, by design, what does not cover all Windows errors. However, other Windows codes are covered too. In VS2017, `std::error_code(ERROR_INVALID_PARAMETER, std::system_category()).message();` gives "The parameter is incorrect." as expected. – mloskot May 26 '17 at 21:24
  • @RustyX Not true. System error codes should be used with `system_category`, **and** it will be comparable to `std::errc` constants. If using Visual C++ 2015 or later (available when you commented), it is true that `std::error_code(ERROR_FILE_NOT_FOUND, std::system_category()) == std::errc::no_such_file_or_directory` *and* `std::error_code(ERROR_PATH_NOT_FOUND, std::system_category()) == std::errc::no_such_file_or_directory`. – Yongwei Wu Sep 23 '17 at 13:52
  • I can add to this, that `boost::system::error_code(::GetLastError(), boost::system::system_category())` works as expected on msvc2013; boost 1_59 at least – Vasilly.Prokopyev Feb 04 '19 at 18:11
9

Be aware that comparing a std::error_code in the category of std::system_category() doesn't generally work with the std::errc enumeration constants depending on your vendor. E.g.

std::error_code(ERROR_FILE_NOT_FOUND, std::system_category()) != std::errc::no_such_file_or_directory)

Certain vendors require using std::generic_category() for that to work.

In MinGW std::error_code(ERROR_FILE_NOT_FOUND, std::system_category()).message() won't give you the correct message.

For a truly portable and robust solution I would recommend subclassing both std::system_error and std::system_category to windows_error and windows_category and implement the correct functionality yourself. YMMV, VS2017 has been reported to work as one would expect.

Community
  • 1
  • 1
Rian Hunter
  • 91
  • 1
  • 2
  • 2
    Someone has got to have made this alreadyright? But I can't find one :( – Mooing Duck Oct 15 '13 at 21:05
  • I am writing in 2017, so I am at a big advantage. This said, there are several problems with your answer. The reason your first example failed was because your should have used `ERROR_FILE_NOT_FOUND`. Secondly, even `ERROR_PATH_NOT_FOUND` will work under Visual C++ 2017 (but not 2013), as long as you use `system_category`. Yes, it only works correctly when one uses `system_category`, but not `generic_category`. Microsoft has made it work very well. – Yongwei Wu Sep 23 '17 at 13:33