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.