Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What error codes can occur with CopyFileEx?

Tags:

c++

winapi

I'm writing some C++ code that needs to call the CopyFileEx function. The documentation for CopyFileEx, like most other WIN32 functions, says:

If the function fails, the return value is zero. To get extended error information, call GetLastError.

Which is all well and good - however does anyone know where I can find a list of the error codes that a specific API function may return via GetLastError? In this case I want to handle different error conditions in different ways but without a list of the error codes for this function I'm going to be reduced to generating the error conditions I want to handle just to see what error code is prodcued or going through the system error codes from numbers 0 to 15999 trying to guess which ones might apply!

Edit: Here is a little more context to help explain the issue and why I want to know if there is a definitive list of error codes that can be returned by a function anywhere.

The code will be used as part of a Windows service so while there are users they won't always be there to respond to errors. I need to be able to distinguish between errors that don't need reporting every time, if a file is locked I'm just to re-try it again later. If I don't have permissions to read a particular file I can log the problem and carry on, if the destination directory is unreadable or is full then I want the service to stop and to trigger a reporting process that will atrract the attention of a user.

Without a comprehensive list of the ways that CopyFileEx can fail I'm finding it hard to do this.

like image 245
Jackson Avatar asked Sep 04 '09 09:09

Jackson


1 Answers

Microsoft doesn't give a list of all error codes an API might return for the simple reason that the list may change over time and various implementations of Windows, installed drivers or simple oversight (APIs often return errors caused by other APIs called within the one you called).

Sometimes the docs call out specific errors that are of particular interest for users of that API, but in general they will not has a definitive complete list of errors. Nor should they, which is unfortunate, but is a fact of life.

I sympathize with your plight - there are many times I would have liked this kind of information so I could have a better idea of how to handle problems that should be anticipated - particularly those that have a reasonable recovery path. Usually I try to deal with this by testing to find the failure behavior of the APIs, and I'd like to avoid that because it's a pain and it doesn't help much with ensuring that I've covered all the scenarios or against future differences.

However, covering all the scenarios (with a comprehensive list of error codes) or protecting against future changes is really an impossible goal. Consider how Microsoft might have to manage documenting all possble error codes in Win32:

Say the Win32 API has only 2 functions: foo() and bar(). foo() might generate its own error, ERROR_FOO and bar() might generate its own error, ERROR_BAR. However, foo() calls bar(), so foo() might also return ERROR_BAR if its call to bar() returns that error.

The docs reflect the following:

  • foo() may retun either ERROR_FOO or ERROR_BAR
  • bar() may return ERROR_BAR

Now, when API v2 is released, bar() has been extended to also return ERROR_BAZ. for something the size of this API it's simple to manage that the docs for bar() need to be updated to add the new error code (however, note that for an API as large as the real Win32 and an organization as large as MS, the same might not be true, but lets assume it is).

However, the guy adding the new error to bar() has no direct visibility to the fact the foo()'s behavior has also changed in terms of what errors it might return. In an API small as this, it's probably not a big deal - in something like Win32 it would be a mess. Now throw in the fact that Win32 can be dependant on 3rd party code (drivers, plug-ins, COM objects, etc) and the task is now pretty near impossible.

Actually that's not necessarily a great example, since if the error codes were part of the contract of an API ERROR_BAZ should have never come into the picture.

So here's another scenario: the API has an OpenObject() function that can return ERROR_NO_MEMORY or ERROR_NOT_FOUND. When this system was first developed, it had no concept of security (say like MS-DOS), but a new release adds access controls. Now we'd like OpenObject() to be able to return ERROR_ACCESS_DENIED, but it can't because that would change the contract, so a new API OpenObjectEx() is added to deal with that situation. There are at least 2 problems here:

  • You'll get an explosion of APIs over time that really add little or no value over the old APIs
  • what should happen to a legacy application that calls the old OpenObject() API and fails because of access restrictions? Neither of the contracted error returns would tell the truth about what the problem is.

This problem is one of the reasons that exception specifications (in C++ or Java) are considered by many to have been a bad idea.

like image 189
Michael Burr Avatar answered Nov 05 '22 17:11

Michael Burr