如何使用硬件ID提取器修复Ntdll.dll APPCRASH?

时间:2015-01-23 19:21:04

标签: c# pinvoke

我正在使用http://www.soft.tahionic.com/download-hdd_id/index.html中的硬件ID提取程序库(用Delphi编写),目的是生成唯一的系统指纹。

图书馆非常好,不像我在市场上看到的任何其他东西,但它的主要问题是它在运行.NET应用程序时不稳定,这意味着它有时可以工作,有时它可以工作对于一些函数调用,然后主应用程序崩溃,或者大多数时候应用程序在调用dll函数时立即崩溃。

正如图书馆的开发人员指出的那样(在我收到的最后一封支持电子邮件中),错误是ntdll.dll,正如我自己看到的那样: enter image description here

以下是我为了测试dll函数而创建的演示项目的链接(为了确保没有其他任何干扰,演示应用程序执行此操作,并且只调用dll函数)。 http://www.mediafire.com/download/1jws7zh9218v88a/HardwareIdExtractDllTest.zip 该存档包含带有源代码的Visual Studio 2013项目和一个编译的演示应用程序,如下所示: enter image description here

dll包含的函数列表可以在这里找到: http://www.soft.tahionic.com/download-hdd_id/hardware%20id%20programming%20source%20code/exported%20functions%20for%20non-Delphi.html

如果有人知道并且愿意测试演示项目/应用程序以针对该问题进行测试或个人意见,然后与我分享可能的解决方案,我将不胜感激。

如果您认为可以采取任何措施,请告诉我是否可以采取任何措施来进一步协助解决此问题。

编辑:这就是我宣布dll功能的方式

    [DllImport("HardwareIDExtractorC.dll")]
    private static extern bool EnterKey(int key);

    [DllImport("HardwareIDExtractorC.dll")]
    private static extern bool IsCPUIDAvailable();

    [DllImport("HardwareIDExtractorC.dll")]
    private static extern int GetCPUCount();

    [DllImport("HardwareIDExtractorC.dll")]
    private static extern byte CoreNumber2CoreMask(byte cpuCore);

    [DllImport("HardwareIDExtractorC.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "GetCPUID")]
    [return: MarshalAs(UnmanagedType.LPStr)]
    private static extern string GetCPUID(byte cpuCore);

    [DllImport("HardwareIDExtractorC.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "GetCpuIdNow")]
    [return: MarshalAs(UnmanagedType.LPStr)]
    private static extern string GetCpuIdNow(); 

    [DllImport("HardwareIDExtractorC.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "GetIDESerialNumber")]
    [return: MarshalAs(UnmanagedType.LPStr)]
    private static extern string GetIDESerialNumber(byte driveNumber);

1 个答案:

答案 0 :(得分:3)

失败的函数是返回string的函数。这样的p / invoke将返回值编组为指向空终止字符数组的指针,然后对非托管代码返回的原始指针调用CoTaskMemFree

如果概率接近1,那么在COM堆上没有分配字符串,因此错误可能出现在C#p / invoke声明中。那么在ntdll中出现访问冲突是非常合理的。

因此,要取得进展,您需要修复p / invoke调用。我无法告诉你如何这样做,因为你没有显示非托管函数声明。或者,更重要的是,如何分配内存。


documentation

有一些线索
procedure ReleaseMemory (P: PAnsiChar); stdcall;

我认为这告诉我们DLL必须通过调用此函数来释放DLL返回的字符串。大概是因为它们是由DLL的堆分配器分配的。

因此,使用IntPtr作为返回文本的函数的返回类型。调用Marshal.PtrToStringAnsi转换为C#字符串。然后将指针传递给ReleaseMemory

例如:

[DllImport(DllPath, CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr GetCPUID(ushort CoreMask);

[DllImport(DllPath, CallingConvention = CallingConvention.StdCall)]
private static extern void ReleaseMemory(IntPtr P);

....

IntPtr ptr = GetCPUID(CoreMask);
string cpuid = Marshal.PtrToStringAnsi(ptr);
ReleaseMemory(ptr);