为啥 `[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 会以这种方式弹出?