inquam
inquam

Reputation: 12932

Is it possible to check if error code has been retrived using GetLastError

If you have a large system that automatically shows a nice window explaining a caught exception it would be nice to be able to present the error code along with the message (for further investigation). But since some functions calls are to failing windows functions, which set an error code, and some are local failing functions that don't set the error code I wonder if there is a way to check if the last set error code has been "retrieved" already.

Let's say we have a piece of code

if (!CopyFile(("c:\foobar.txt", "d:\foobar.txt",FALSE))
{
  throw FooBarException("bla bla bla");
}

Here it would be possible to automatically add the error code to the error message since CopyFile is a function that sets the error code on failure. Now, we could add the error code "manually" within the if statement and append it to the error string passed when creating the exception. But to not have to change thousands of places in existing code we could have the constructor of the FooBarException automatically fetch and append the error code. But this also raises the issue in question.

What if some code that doesn't set the error code causes a FooBarException to be raised. Then the constructor would GetLastError but get an error code that might not be connected to the current exception at all.

But if the constructor of FooBarException could call some LastErrorRetrived (or something similar) and get true if the error code has already been retrieved before it ould ignore appending the error code and assume it's connected to an earlier error.

Now I understand this can go haywire if one does not actually "retrieve" the error code after every windows function that can fail and set the error code. But let's assume this is done.

Upvotes: 2

Views: 518

Answers (2)

IInspectable
IInspectable

Reputation: 51385

Short answer: No.

The value returned by GetLastError is simply a global (per-thread) object without any logic attached. It can be accessed through GetLastError, SetLastError and the mysterious RestoreLastError.

I'm afraid I have to break the news: Retrofitting error handling into a system that wasn't prepared for it is tedious.

There is really very little you can do outside of implementing several exception classes (for Win32 error codes, COM HRESULTs, etc.) and changing each and every invocation.

Upvotes: 2

Ivan
Ivan

Reputation: 2057

GetLastError() just gets thread's last-error code value and that's all. So, I believe there is no way to know was it called once or a few times. Moreover, I don't really think you need to.

The best solution here is to create WinAPIException class derived from some base class (for example, std::exception ). In constructor WinAPIException should call GetLastError() before any other WinAPI call. It guarantees that the error value isn't change.

if( !CopyFile("c:\foobar.txt", "d:\foobar.txt",FALSE) )
    throw WinAPIException("Houston, we have a WINAPI problem");

If you check result after non-WinAPI function call - just use other exception class (derived from the same base class):

if( std::cin.get() < 0 )
    throw std::runtime_error("Houston, we have runtime problem");

Thus, you can use single try...catch statement to catch both exceptions:

try {
    ...
} catch( std::exception &e ) {
    ...
}

Upvotes: 1

Related Questions