I am know NTSTATUS that i will get in case of specific error, but i got hresult, not ntstatus from pinvoke. So how to convert specific NTSTATUS value to the Hresult.
I tried with no success:
class Program
{
private const int FacilityNtBit = 0x10000000;
//#define STATUS_DUPLICATE_OBJECTID ((NTSTATUS)0xC000022AL)
private const int STATUS_DUPLICATE_OBJECTID = unchecked((int) (0xC000022A));
// HResult that is returned for the STATUS_DUPLICATE_OBJECTID
private const int CorrectHrStatusDuplicateObjectid = -2147019886;
static void Main(string[] args)
{
int res = HRESULT_FROM_NT(STATUS_DUPLICATE_OBJECTID);
Debug.Assert(res == CorrectHrStatusDuplicateObjectid, "Must be the same");
}
private static int HRESULT_FROM_NT(int ntStatus)
{
//#define HRESULT_FROM_NT(x) ((HRESULT) ((x) | FACILITY_NT_BIT))
return ntStatus | FacilityNtBit;
}
}
NTSTATUS
you have0xC000022A
: STATUS_DUPLICATE_OBJECTID
- The attempt to insert the ID in the index failed because the ID is already in the index.)
HRESULT
you want0x80071392
:
FACILITY_WIN32
- This region is reserved to map undecorated error codes into HRESULTs.)ERROR_OBJECT_ALREADY_EXISTS
- The object already exists.)The problem is that there are multiple representations of the same error:
0xC000022A
5010
0xD000022A
(converting the NSTATUS to an HRESULT)
0x80071392
(converting the Win32 error to an HRESULT)
Not all NTSTATUS codes can be converted to Win32. Iin that case, trying to go through RtlNtstatusToDosError
will give you the error code ERROR_MR_MID_NOT_FOUND
:
The system cannot find message text for message number 0x%1 in the message file for %2.
This is why it's best to keep the real error message.
The real issue i assume being experienced is how to convert an NTSTATUS
to an error message that can be displayed to the user. For that you want Microsoft Knowledge Base article:
KB259693 - How to translate NTSTATUS error codes to message strings
Most Kernel Mode API functions return NTSTATUS values. To translate these status values to messages by using the FormatMessage API function, you must reference the NtDLL.dll module in the parameter list.
void DisplayError(DWORD NTStatusMessage) { LPVOID lpMessageBuffer; HMODULE Hand = LoadLibrary("NTDLL.DLL"); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE, Hand, Err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMessageBuffer, 0, NULL ); // Now display the string. // Free the buffer allocated by the system. LocalFree( lpMessageBuffer ); FreeLibrary(Hand); }
The mapping of native OS error codes to the winapi layer error codes is non-trivial. There's just no correspondence whatsoever between 5010 and 0xc000022a. The mental image to use is a giant switch statement hidden inside ntdll.dll that translates from one to the other. Reluctantly exposed by Microsoft, you'd normally have to jump through hoops to use it. Actually easier from pinvoke code since it already uses GetProcAddress() to find exported functions.
But as long as you are making a winapi call, you should only expect to get a winapi error code and make no attempt to translate it yourself. It can be wrapped in an HRESULT, simply 0x80070000 + error. The native OS error code does bleed through sometimes, particularly for SEH exception codes, but is always easy to recognize.
This question would have been easier to answer accurately if you had mentioned the winapi function you are trying to use btw.
As an alternative to RtlNtStatusToDosError(Status)
to convert an NTSTATUS
to a Win32 error code, I've abused GetOverlappedResult()
(from kernel32.dll) as follows:
DWORD
ConvertNtStatusToWin32Error(NTSTATUS ntstatus)
{
DWORD oldError;
DWORD result;
DWORD br;
OVERLAPPED o;
o.Internal = ntstatus;
o.InternalHigh = 0;
o.Offset = 0;
o.OffsetHigh = 0;
o.hEvent = 0;
oldError = GetLastError();
GetOverlappedResult(NULL, &o, &br, FALSE);
result = GetLastError();
SetLastError(oldError);
return result;
}
Then the Win32 error code can be converted to a HRESULT
using HRESULT_FROM_WIN32(error)
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With