Tuesday, September 13, 2011

WINERROR

WINERROR has it's roots in DOS which is why it is also referred to as DosError. RtlNtStatusToDosError() is an example which will be discussed more later. DOS errors were in turn derived from the C standard library errno.

Values of WINERROR are defined in winerror.h and look like ERROR_SUCCESS. They are an enumeration that are expected to fit in the lower 16bits of the 32bit WINERROR type, more on that later. WINERROR values are sometimes returned through the API result, but often an API will return a BOOL or HANDLE and pass any errors to SetLastError() and then return FALSE or an invalid-handle, the caller will retrieve the WINERROR by calling GetLastError(). ERROR_SUCCESS is the only success value for WINERROR.

Api Examples:

DWORD ApiReturningWinerror(HANDLE handle)
{
  if (handle == INVALID_HANDLE_VALUE) {
    return ERROR_INVALID_PARAMETER;
  }
  return ERROR_SUCCESS;
}

DWORD winerror = ERROR_SUCCESS;
HANDLE handle = INVALID_HANDLE_VALUE;
winerror = ApiReturningWinerror(handle);
if (winerror != ERROR_SUCCESS)
{
  printf("ApiReturningWinerror returned %d", winerror);
  exit();
}

BOOL ApiReturningBool(HANDLE handle)
{
  if (handle == INVALID_HANDLE_VALUE) {
    SetLastError(ERROR_INVALID_PARAMETER);
    // The caller should call GetLastError()
    return FALSE;
  }
  // the common pattern is that SetLastError
  // is only called on failure.
  // Thus the caller should NOT call GetLastError()
  return TRUE;
}

DWORD winerror = ERROR_SUCCESS;
HANDLE handle = INVALID_HANDLE_VALUE;
if (!ApiReturningBool(handle))
{
  winerror = GetLastError();
  printf("ApiReturningBool returned %d", winerror);
  exit();
}

Conversions to WINERROR

NTSTATUS ntstatus = STATUS_SUCCESS;
DWORD winerror = RtlNtStatusToDosError(ntstatus);
if (winerror == ERROR_MR_MID_NOT_FOUND)
{
  // there is no conversion
  return ERROR_UNIDENTIFIED_ERROR;
#if 0
  // The following is common, but doesn't work out well
  // especially when combined with HRESULT_FROM_WIN32
  // and NTSTATUS_FROM_WIN32
  return ntstatus;
#endif
}

HRESULT hr = S_OK;
DWORD winerror = ERROR_SUCCESS;
if (SUCCEEDED(hr))
{
  winerror = S_OK;
} else if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
{
  winerror = HRESULT_SCODE(hr);
} else
{
  winerror = ERROR_UNIDENTIFIED_ERROR;
}

Conversions from WINERROR

DWORD winerror = ERROR_SUCCESS;
HRESULT hr = HRESULT_FROM_WIN32(winerror);

DWORD winerror = ERROR_SUCCESS;
NTSTATUS ntstatus = NTSTATUS_FROM_WIN32(winerror);

Both of the FROM_WIN32 macros work by masking only the lower 16bits of the WINERROR value into the resulting NTSTATUS or HRESULT

No comments:

Post a Comment