无法将方法CryptGetHashParam中的指针(IntPtr)复制到byte []

时间:2011-01-24 22:08:43

标签: c# memory marshalling protected

我整天都在研究这个问题,我仍然坚持下去 我把这个代码从c / c ++移植到c#im这么近但我得到了这些例外

抛出了类型'System.ExecutionEngineException'的异常。 和 尝试读取或写入受保护的内存。这通常表明其他内存已损坏。

这里是代码,代码没有清理/优化但导致我仍然在测试它

    public unsafe static void GetHash(string data, byte[] hash)
    {
        byte[] input = System.Text.UnicodeEncoding.Unicode.GetBytes(data);
        hash = new byte[128];
        IntPtr hProv = IntPtr.Zero;
        IntPtr hHash = IntPtr.Zero;

        Crypto.CryptAcquireContext(ref hProv, string.Empty, string.Empty, Crypto.PROV_RSA_FULL, 0);

        if (Crypto.CryptCreateHash(hProv, Crypto.CALG_SHA1, IntPtr.Zero, 0, ref hHash))
        {
            if (Crypto.CryptHashData(hHash, input, ((input.Length) + 1) * 2, 0))
            {
                byte[] buffer = new byte[20];
                IntPtr pBuffer = IntPtr.Zero;
                int length = 20;

                if (Crypto.CryptGetHashParam(hHash, Crypto.HP_HASHVAL, ref pBuffer, ref length, 0))
                {
                    Crypto.CryptDestroyHash(hHash);
                    Crypto.CryptReleaseContext(hProv, 0);  
                    byte tail = 0;

                    unsafe
                    {
                        //no matter what i do it stops here!!!!! :(
                        //one error is "Exception of type 'System.ExecutionEngineException' was thrown."
                        //the other is "System.AccessViolationException crossed a native/managed boundary
                        //Attempted to read or write protected memory. This is often an indication that other memory is corrupt."

                        try
                        {
                             //-------------------------- This is where the exepctions starts
                            //I have commented the code, cause im kinda getting tired of this Exception
                            //I tried 2 ways of getting a byte[] from a pointer

                            //the 1e way, does not work
                            //for (int i = 0; i < length; i++)
                                //buffer[i] = (byte)Marshal.ReadByte(pBuffer, i);

                            //the 2e way does not work
                            //System.Runtime.InteropServices.Marshal.Copy(pBuffer,buffer, 0, 20);

                            //--------------------------
                        }
                        catch (Exception ex)
                        { 

                        }
                    }

                    //there is more code here, but i removed
                    //since i only want till where code goes sofare
                }
            }
        }
    }
希望有人可以帮助我,

Thnx提前

JB

2 个答案:

答案 0 :(得分:2)

我在没有使用不安全或固定声明的情况下修复它,我所做的就像大多数编码tmp问题一样简单

我有这个类Crypto,我有所有advapi.dll函数,函数返回一个指向内存中字节数组的指针,这就是我改变之前所需的函数。

        [DllImport("advapi32.dll", SetLastError = true)]
    public static extern bool CryptGetHashParam(
        IntPtr hHash,
        Int32 dwParam,
        ref IntPtr pbData, // this is where my problem was!!!!
        ref Int32 pdwDataLen,
        Int32 dwFlags

我将功能更改为

        [DllImport("advapi32.dll", SetLastError = true)]
    public static extern bool CryptGetHashParam(
        IntPtr hHash,
        Int32 dwParam,
        Byte[] pbData, //i changed it from IntPtr to byte array
        ref Int32 pdwDataLen,
        Int32 dwFlags

这解决了我的腐败记忆问题 希望这个问题可以帮助其他人使用CryptGetHashParam

我从c / c ++移植了这段代码,因为网上没有c#样本,所以这里是第一个。

所有人都试图帮助我,但我自己修理了

JB

答案 1 :(得分:1)

我不确定,但可能是因为你的.Net对象没有固定在内存中。见:http://dotnet.dzone.com/news/net-memory-control-use-gchandl。它的要点是.Net对象在你通过互操作传递后可以在内存中移动,当发生这种情况时,东西开始变得疯狂。

不幸的是,我现在正在使用上网本,不能自己尝试。这有帮助吗?

相关问题