P/Invoke 不安全代码应该出现哪些异常?

发布于 2024-09-11 06:27:59 字数 934 浏览 1 评论 0原文

在我的解决方案中,我编写了以下内容:

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern unsafe bool CopyFileEx(string lpExistingFileName,  
 string lpNewFileName, CopyProgressRoutine lpProgressRoutine, IntPtr lpData,  
 Boolean* pbCancel,    CopyFileFlags dwCopyFlags);

...

bool result;

unsafe{
  result = CopyFileEx(sourceFile, targetFile, null, IntPtr.Zero,  
                      null /* pointer */, 0);
}

if(!result)
    Win32Exception exc = new Win32Exception(Marshal.GetLastWin32Error()); 
// parameter could be omitted according to Win32Exception constructor 
// implementation

假设 CopyFileEx 是使用 DllImport 属性的 SetLastError = true 参数导出的,我是否有机会在这里得到任何未停止的异常?

我对包装在 RuntimeWrappedException 实例中的非 CLR 异常特别感兴趣。在 C++ 中,“throw 1”是一个有效的构造。那么,我应该从此类 P/Invoke 调用中期待哪些异常,以及从哪里可以获得有关异常的此类信息(MSDN 没有提及有关 CopyFileEx 的异常)?

In my solution I've written the following:

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern unsafe bool CopyFileEx(string lpExistingFileName,  
 string lpNewFileName, CopyProgressRoutine lpProgressRoutine, IntPtr lpData,  
 Boolean* pbCancel,    CopyFileFlags dwCopyFlags);

...

bool result;

unsafe{
  result = CopyFileEx(sourceFile, targetFile, null, IntPtr.Zero,  
                      null /* pointer */, 0);
}

if(!result)
    Win32Exception exc = new Win32Exception(Marshal.GetLastWin32Error()); 
// parameter could be omitted according to Win32Exception constructor 
// implementation

In the assumption that CopyFileEx was exported with SetLastError = true parameter of DllImport attribute, do I have a chance to get any unhalted exception here?

I'm specifically interested in non-CLR exceptions which are wrapped in RuntimeWrappedException instance. In C++ "throw 1" is a valid construct. So what exceptions should I expect from such P/Invoke calls and where I can obtain such information regarding exceptions (MSDN says nothing regarding exceptions from CopyFileEx)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

夜雨飘雪 2024-09-18 06:27:59

如果 DLL 使用 Win32 结构化异常处理系统,则 DLL 抛出的任何异常都将被转换为 OutOfMemoryExceptionAccessViolationExceptionNullReferenceException(很少见) ),或SEHException

RuntimeWrappedException 仅在托管 C++ 抛出非Exception 派生对象时使用。它不用于非托管 DLL。如果您有一个执行抛出 1托管 C++ DLL,那么您可以捕获RuntimeWrappedException

SEHException 充当来自非托管 DLL 的不可映射 SEH 异常类型的捕获器。这将包括任何 C++ 类或 throw 1 示例。 AFAIK,没有办法从 SEHException 中提取 C++ 特定的异常信息,尽管我确信如果你足够努力的话它是可以破解的。

请注意,有一些 DLL 不使用 Win32 结构化异常处理系统。最值得注意的是 Cygwin DLL。在这种情况下,任何 C++ 异常都可能导致进程崩溃或至少导致线程崩溃。当然,所有 Windows DLL(包括定义 CopyFileEx 的 DLL)都使用 Win32 结构化异常处理,Microsoft C++ 编译器创建的任何非托管 DLL 也是如此。

另请注意,Win32 API(包括 CopyFileEx)通常不会使用 Win32 结构化异常报告错误;他们通过 GetLastError 报告它们。让大多数 Win32 函数抛出 Win32 结构化异常的唯一方法是向其传递极其无效的参数(例如要求它写入 ntdll.dll 的中间)。

If a DLL uses the Win32 structured exception handling system, then any exceptions thrown by the DLL will be translated to OutOfMemoryException, AccessViolationException, NullReferenceException (rarely), or SEHException.

RuntimeWrappedException is only used when managed C++ throws a non-Exception-derived object. It is not used for unmanaged DLLs. If you had a managed C++ DLL that did a throw 1, then you could catch RuntimeWrappedException.

SEHException acts as a catch-all for the unmappable types of SEH exceptions from unmanaged DLLs. This would include any C++ class, or the throw 1 example. AFAIK, there is no way to pull the C++-specific exception info out of SEHException, though I'm sure it's hackable if you try hard enough.

Note that there are a few DLLs that do not use the Win32 structured exception handling system. Most notably Cygwin DLLs. In that case, any C++ exception is likely to crash the process or at least your thread. Naturally, all the Windows DLLs (including the one defining CopyFileEx) do use Win32 structured exception handling, as do any unmanaged DLLs created by Microsoft's C++ compiler.

Also note that the Win32 API (including CopyFileEx) does not normally report errors using Win32 structured exceptions; they report them via GetLastError. The only way to get most Win32 functions to throw a Win32 structured exception is to pass it wildly invalid arguments (such as asking it to write into the middle of ntdll.dll).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文