为啥 `[DllImport]` 会以 `RtlSecureZeroMemory` 的入口点失败,即使它是一个有据可查的入口点?

Posted

技术标签:

【中文标题】为啥 `[DllImport]` 会以 `RtlSecureZeroMemory` 的入口点失败,即使它是一个有据可查的入口点?【英文标题】:Why does `[DllImport]` fail with an entry point of `RtlSecureZeroMemory`, even though it is a well documented entry point?为什么 `[DllImport]` 会以 `RtlSecureZeroMemory` 的入口点失败,即使它是一个有据可查的入口点? 【发布时间】:2019-04-13 10:05:33 【问题描述】:

使用下面的代码尝试使用 kernel32 函数 SecureZeroMemory 失败,并出现 System.EntryPointNotFoundException - 即使它有很好的文档记录 here, on PInvoke 和 here, on SO。在目标 .NET Framework 4.7.2 上运行完全正常的 Windows 10 Pro。

        /// <summary>
        /// A kernel32 function that destroys all values in a block of memory
        /// </summary>
        /// <param name="destination">The pointer to the start of the block to be zeroed</param>
        /// <param name="length">The number of bytes to zero</param>
        /// <returns></returns>
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, EntryPoint = "RtlSecureZeroMemory")]
        public static extern void SecureZeroMemory(IntPtr destination, IntPtr length);

【问题讨论】:

你在写什么样的 .net 应用? WPF 应用程序,因此仅限 Windows 不可能,因为 RtlSecureZeroMemory 不是系统 DLL 导出的函数。它是一个函数inlined in winnt.h 本质上,当在 C/C++ 项目中包含 winnt.h 时,该函数的代码正在成为被编译代码的一部分。现在,显然,您不能在 C# 中将 C 头文件与 C 代码内联... :-( 所以这些记录它的人一定只是猜到了。将__declspec(dllexport) 包装到 C++ DLL 中的最佳方法是什么? 是的,你可以这样做。 【参考方案1】:

此功能已记录在案,但您包含的两个链接都不是文档。要了解发生了什么,您应该首先阅读此处的实际文档:https://msdn.microsoft.com/en-us/library/windows/desktop/aa366877(v=vs.85).aspx

上面写着:

这个函数被定义为 RtlSecureZeroMemory 函数(参见 WinBase.h)。 RtlSecureZeroMemory 的实现是内联的,可以在任何版本的 Windows 上使用(参见 WinNT.h。)

“提供内联”的意思是该函数是在头文件中定义的,而不是由任何系统 DLL 导出的。这意味着它不能被 p/invoke 调用。

【讨论】:

谢谢!我将尝试围绕它编写一个 C++ 包装器以使其工作。 :) 为什么,它所做的只是将内存归零,确保代码不会被优化出来。当然,这可以在纯 C# 中完成。使用对Marshal.Copy 的调用将零字节强制到非托管内存中。你为什么要这样做呢? 我做的这个项目主要是为了体验,所以我可以使用Array.Clear(),但是我很好奇使用[DllImport]所以试了一下

以上是关于为啥 `[DllImport]` 会以 `RtlSecureZeroMemory` 的入口点失败,即使它是一个有据可查的入口点?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 UIPopoverController 会以这种方式弹出?

为啥 Node.js 会以这种方式执行?

为啥 IE 会以不同的方式呈现这个 HTML 表格?

为啥添加两个 .OrderBy(或 .OrderByDescending)语句会以相反的顺序应用排序?

为啥这个非常棘手的计算属性名称函数会以它的方式工作?

为啥 Visual Studio 在调试时会以不同的方式处理 ANSI Escape 代码?