Convert Win32 error using vbObjectError and HRESULT_FROM_WIN32
HRESULT_FROM_WIN32 is the name of a macro used in C to convert a WIN32 error into an HRESULT error (although since XP it has been replaced by an inline function).
The Win32 errors are easily converted into HRESULT errors. Win32 errors are 16 bit values, whilst HRESULT errors are 32 bit values. The additional 16 bits define the Facility and the Severity of the error. HRESULT encapsulates Win32 errors when the Facility code is set to FACILITYT_WIN32 and severity set to SEVERITY_ERROR and the low 16 bits contain the Win32 error number.
vbObjectError is the exact value of an HRESULT with the facility code set to FACILITY_ITF.
Visual Basic will recognize a returning HRESULT from a function and process it automatically using Err.Raise. When you raise an error in Visual Basic with "Err.Raise vbObjectError Or nMyError," you are unknowingly using an HRESULT with a status code of nMyError.
It is a small step to convert from a FACILITY_ITF used in vbObjectError to a FACILITY_WIN32 required to encapsulate Win32 API errors. Win32 errors are then recognised by Visual Basic as an HRESULT and the Err.Description includes the description of the Win32 error.
The conversion is to take the 16 bit Win32 errors and combine this with FACILITY_WIN32 and SEVERITY_ERROR. It is not necessary to use the vbObjectError but because of the HRESULT connection, it illustrates how Visual Basic can use HRESULT errors.
The constant vbObjectError is derived from the FACILITY_ITF code together with the Error severity code.
This vbObjectError can be used to create a new constant vbWin32Error by adding an adjustment for the different FACILITY codes FACILITY_ITF and FACILITYT_WIN32.
The Win32API error can then be converted to an HRESULT error by adding this constant vbWin32Error to the error, and the error can be trapped using the Visual Basic Err.Raise method, and the error description can be accessed using Err.Description.
The resulting Err.Description identifies the error as a Win32 HRESULT by starting the error description with "Automation error"
The function below HRESULT_FROM_WIN32 converts a Win32 Error into an HRESULT, and the function WIN32_FROM_HRESULT converts HRESULT error back into Win32 Error.
These functions can be used to raise a VB error from a Win32 api function, using the err.raise method:
References
Update July 6th 2018
HRESULT_FROM_WIN32 is the name of a macro used in C to convert a WIN32 error into an HRESULT error (although since XP it has been replaced by an inline function).
The Win32 errors are easily converted into HRESULT errors. Win32 errors are 16 bit values, whilst HRESULT errors are 32 bit values. The additional 16 bits define the Facility and the Severity of the error. HRESULT encapsulates Win32 errors when the Facility code is set to FACILITYT_WIN32 and severity set to SEVERITY_ERROR and the low 16 bits contain the Win32 error number.
vbObjectError is the exact value of an HRESULT with the facility code set to FACILITY_ITF.
Visual Basic will recognize a returning HRESULT from a function and process it automatically using Err.Raise. When you raise an error in Visual Basic with "Err.Raise vbObjectError Or nMyError," you are unknowingly using an HRESULT with a status code of nMyError.
It is a small step to convert from a FACILITY_ITF used in vbObjectError to a FACILITY_WIN32 required to encapsulate Win32 API errors. Win32 errors are then recognised by Visual Basic as an HRESULT and the Err.Description includes the description of the Win32 error.
The conversion is to take the 16 bit Win32 errors and combine this with FACILITY_WIN32 and SEVERITY_ERROR. It is not necessary to use the vbObjectError but because of the HRESULT connection, it illustrates how Visual Basic can use HRESULT errors.
The constant vbObjectError is derived from the FACILITY_ITF code together with the Error severity code.
vbObjectError = FACILITY_ITF or Severity_Error
= (4 << 16) or 0x80000000
This vbObjectError can be used to create a new constant vbWin32Error by adding an adjustment for the different FACILITY codes FACILITY_ITF and FACILITYT_WIN32.
vbWin32Error = vbObjectError + ((FACILITY_WIN32 - FACILITY_ITF) * (2 ^ 16))
The Win32API error can then be converted to an HRESULT error by adding this constant vbWin32Error to the error, and the error can be trapped using the Visual Basic Err.Raise method, and the error description can be accessed using Err.Description.
The resulting Err.Description identifies the error as a Win32 HRESULT by starting the error description with "Automation error"
The function below HRESULT_FROM_WIN32 converts a Win32 Error into an HRESULT, and the function WIN32_FROM_HRESULT converts HRESULT error back into Win32 Error.
Code:
Private Const FACILITY_ITF = 4
Private Const FACILITY_WIN32 = 7
Private Const vbWin32Error = vbObjectError + ((FACILITY_WIN32 - FACILITY_ITF) * (2 ^ 16))
Public Function HRESULT_FROM_WIN32(LastDllError As Long) As Long
If (((LastDllError And (Not &HFFFF&)) = 0) and (LastDllError <>0)) Then
HRESULT_FROM_WIN32 = (LastDllError Or vbWin32Error)
Else
HRESULT_FROM_WIN32 = LastDllError
End If
End Function
Public Function WIN32_FROM_HRESULT(HRESULT As Long) As Long
If ((HRESULT And (Not &HFFFF&)) = vbWin32Error) Then
WIN32_FROM_HRESULT = (HRESULT And &HFFFF&)
Else
WIN32_FROM_HRESULT = HRESULT
End If
End Function
Code:
Private Sub UsageExample()
Dim RetApi As Long
On Error GoTo EH
' RetApi = Win32ApiFunction() ' returns 0 if error, <> 0 if successful
If RetApi = 0 Then
Err.Raise HRESULT_FROM_WIN32(Err.LastDllError)
End If
Exit Sub
EH:
MsgBox "Error Nos : " & WIN32_FROM_HRESULT(Err.Number) _
& vbCrLf & "Error : " & Err.Description
End Sub
References
- Q189134 HOWTO: Raise an Error in Visual Basic From Your C DLL
- MSDN OldNewThing blog - How do I convert an HRESULT to a Win32 error code
- WinError.h
- Platform SDK: COM - Using Macros for Error Handling
- MSDN blog - The evolution of HRESULT_FROM_WIN32
Update July 6th 2018