Win32和COM错误码可以直接转换为SEH异常

当Win32或COM操作失败时,对于没有处理到的小概率错误码,可以直接RaiseException抛出SEH异常,Visual Studio调试器可以捕获这个异常,自动定位到异常抛出点,并显示错误提示信息,方便编程中及时跟踪和处理。

// 检查并抛出Win32 SEH异常
if (f == INVALID_HANDLE_VALUE)
    RaiseException(GetLastError(), 0, 0, NULL);
// 检查并抛出COM SEH异常
if (FAILED(hr))
    RaiseException(hr, 0, 0, NULL);

其实COM错误码(HRESULT)本身就可以作为Win32错误码,因为Win32错误码只要不等于0就是错误。

但Win32错误码不能作为COM错误码,因为COM错误码小于0才是错误。如果需要将Win32错误码作为COM错误码,需要使用HRESULT_FROM_WIN32宏。使用这个宏转换,Win32错误码由0x0000xxxx变为了0x8007xxxx,因此可以作为COM错误码。

// COM错误码可以直接用作Win32错误码
SetLastError(hr);
// Win32错误码必须使用宏转换为COM错误码
return HRESULT_FROM_WIN32(GetLastError());

RaiseException其实是接收NTSTATUS错误码的,和COM错误码一样,NTSTATUS也是小于0表示错误。理论上来说这两种错误码是不能混用的,但是实际上由于用户态SEH使用的NTSTATUS错误码很少,而且并不和任何用户态COM异常冲突,因此可以放心使用。

唯一的疑似冲突的是RPC_E_CALL_REJECTED(0x80010001),在NTSTATUS中是DBG_EXCEPTION_NOT_HANDLED,然而DBG_EXCEPTION_NOT_HANDLED实际上是ContinueDebugEvent的参数,而不是错误码。

https://docs.microsoft.com/windows/desktop/Debug/writing-the-debugger-s-main-loop

https://docs.microsoft.com/en-us/windows/win32/api/debugapi/nf-debugapi-continuedebugevent

实际上微软的<wrl.h>中的Microsoft::WRL::Details::RaiseException函数也将COM错误码直接传给RaiseException。

https://docs.microsoft.com/zh-cn/cpp/cppcx/wrl/raiseexception-function?view=vs-2019

.

发布了29 篇原创文章 · 获赞 1 · 访问量 3383

猜你喜欢

转载自blog.csdn.net/defrag257/article/details/103942751