Get the identifier of a Windows error code - c++

In a program I'm developing I need to gather information about runtime errors. Currently, I am able to gather all the information I need, including the message via FormatMessage, but the identifier of the error (for example, ERROR_SUCCESS). I know that when the application is compiled these identifiers are not actually present in the binaries.
Is there a function in the Windows API which can retrieve these identifiers or do I need to store them with my application?

ERROR_SUCCESS itself is just a constant. I haven't found a way to go from number -> constant identifier.
You could scan WinError.h with Clang and create some kind of table for your application.

Here is a nice example of how you can get the ErrorCode and how to translate it to a more readable message on MSDN.
No need to copy that over, its quite plain:
Retrieving the last error code and message

Related

Is there a way to receive as a string, the errors from DX12?

Example: Here's the debug log for CreateGraphicsPipelineState, it tells me what went wrong:
D3D12 ERROR: ID3D12Device::CreateGraphicsPipelineState: Root Signature doesn't match Vertex Shader: Shader CBV descriptor range (RegisterSpace=0, NumDescriptors=1, BaseShaderRegister=0) is not fully bound in root signature
However, a call to windows FormatMessage(MESSAGE_FROM_SYSTEM...) will return this for the exact same error:
The parameter is incorrect.
The first is obviously far more useful...
We used to have dxerr.lib, and we have source for dxerr.cpp in DXUT. But this doesn't cover DX12. I can't see any way for a shader-tool to retrieve the error and present it to the user from the API.
This can be done with the ID3D12InfoQueue interface, as documented here:
https://learn.microsoft.com/en-us/windows/win32/api/d3d12sdklayers/nn-d3d12sdklayers-id3d12infoqueue
As far as I can tell it's currently not possible to set a callback, which means that you'll need to explicitly query for feedback.
There are two different sources of error/status information involved here. The error code you have returned from the API call is E_INVALIDARG and you obtained a good string for it. This is the status code from the API.
The descriptive message you see in debug output is emitted by Direct3D 12 debug layer, which you loaded during API initialization. It is, generally speaking, an optional component and might be not available in the system while the API itself is available.
To intercept debug output programmatically you can either
utilize this trick: Capture OutputDebugString output
or, attach as a debugger to your application and process debug output event recording the contents

Handling WinAPI error return values

I am currently learning C++ in connection with WinAPI. I am struggling to come up with meaningful error handling strategy for WinAPI functions.
PROBLEM:
Most of WinAPI functions can return 0 in case of error, but in many cases I don't see any information on MSDN as to what could cause such error and how to address / resolve it. Taking GetCursorPos as an example:
Returns nonzero if successful or zero otherwise. To get extended error information, call GetLastError.
(...)
The input desktop must be the current desktop when you call GetCursorPos. Call OpenInputDesktop to determine whether the current desktop is the input desktop. If it is not, call SetThreadDesktop with the HDESK returned by OpenInputDesktop to switch to that desktop.
If I follow the route of GetLastError I am interested in what errors could be returned by that specific function so that I can inspect what can be done about them. But error codes are organized on this MSDN page into 10 groups based on just error number and without any specification of what errors are listed in which group.
When I tried to discover how would OpenInputDesktop help me make my code more bulletproof I discovered that again:
If the function fails, the return value is NULL. To get extended error information, call GetLastError.
To sum it up: almost every function in WinAPI can return value determining occurrence of error and I can get information on the error when it happens using GetLastError function. But no information whatsoever on what kinds of errors I can expect and what steps to make to resolve them.
The examples are many, GetWindowRect is also widely used and MSDN delivers the very same limited information as for GetCursorPos.
QUESTION:
Please are there any standards on how to approach WinAPI function error return values that would retain error handling from becoming just showing a message box and exiting the application? Thank you!
As far as knowing ahead of time what possible error codes can be returned by a particular function, I'm afraid that Microsoft decided long time ago that maintaining such documentation for all functions would be too cumbersome and costly, as an API function may call any number of other API functions, which in turn may call others and so on. Sometimes you get lucky and the MSDN doc calls out error codes specific to that function, as is the case with ReadFile but this is not the case with all functions as you have noticed.
That being said, the standard way of dealing with the error codes returned by GetLastError() is to format them with FormatMessage.
If you passed LANG_USER_DEFAULT for lang ID, this will return the sometimes helpful, sometimes not so helpful error message formatted in the user's chosen locale from the error code. You can show this message to the user. If you wanted to format it in your own language for logging purposes, assuming it's English, you would pass MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US) for lang ID.
And this is the best you can do if the error codes are not documented and you haven't come across them in testing: log them and get the log with other debug info attached to the issue report.

AllocConsole error codes

What error codes can a failed call to AllocConsole generate? On the MSDN website it says If the function fails, the return value is zero. To get extended error information, call GetLastError. But I see no place saying what kinds of errors it can generate.
In most system calls, there is a rather long list of "possible failure scenarios", and that means that you get a large number of possible error codes. For example, some resource in the OS may be full (I expect there is a list of consoles in the OS somewhere, and if that list is full and/or can't be grown, there is some error for that). The Console also needs to have memory as a buffer for the text content, as well as a graphical output buffer (to avoid having to draw every character every time the screen is refreshed) - both of these lead to at least two distinct errors (out of memory, out of graphics memory, and possibly "no way to create a handle for the graphics resource").
A different category of possible errors are permission based ones - maybe your process (based on the user being logged in) doesn't have enough permissions to create a console.
I'm pretty sure the list of actually possible errors is much greater than that.
In summary, don't expect that the errors you can get from a function is limited - if you are interested in a particular set of error codes, then check for those, and do something sane if it isn't one of those. Don't expect that you can't get any other error code.

How to get the version of the given SQL Server Compact Edition database file (.sdf) using OLEDB API?

My C++ app needs to deal with SSCE database files belonging to different versions. Right now, I have no way of knowing the version of the database.
The problem is that if the version of the OLEDB SSCE provider mismatches the version of the database file, IDBInitialize::Initialize() fails with E_FAIL. One has to obtain the respesctive IErrorInfo object to get a meaningful error message.
The point is that the error code of E_FAIL does not tell me whether the failure is because of the version mismatch or for some other reason. In the first case, I should retry with another SSCE provider, while in the second the application should terminate.
How can I implement this logic? Is there some API that I can invoke before calling IDBInitialize::Initialize() to check the version compatibility? Is there a way to get the real error code instead of the opaque E_FAIL?
Thanks.
You can look at the first bytes of the file - see this sample in C# - http://erikej.blogspot.com/2010/08/how-to-upgrade-version-3x-database-file.html

Is a separate message file library for my native Win32 service necessary?

We've got an old legacy win32 service, developed with C++, and we've just recently noticed that when the service starts up and stops, there is an informational message in the event logs about our missing event descriptions. To be more precise, the message looks like this:
The description for Event ID 0 from source [application] cannot be
found. Either the component that raises this event is not installed on
your local computer or the installation is corrupted. You can install
or repair the component on the local computer.
So we understand what this means, basically we're missing a library which has a message table compiled into it. This way when the event ID for changing status (start/stop) arrives, it can look up the message and print it in the event logs.
The question is, for these universal messages (changing status etc) which pretty much every service is going to have, surely there are default message table that we can use, rather than having to go to the trouble of creating another project, just for this, adding registries and updating our installer.
Seems like a lot of hassle for something that should surely be a default somewhere? Like the standard win32 error messages?
I've created a number of managed services in the past, and I'm pretty sure we didn't need to do anything like this before!
So to wrap this up, I guess the answer is that the a new message table/file is always required, regardless (so no there are no default messages you can use), so I'll just have to chuck in a message table into my services resource file and add a registry entry to the installer.
Still find it baffling thought that every native service has it's own 'service has stopped/started' message...!
Thanks!