开发者

C# CreatePipe() -> Protected memory error

I trying to create a pipe using C#. The code is quite simple but when the line with CreatePipe() call is executed I get a System.AccessViolationException with the following error message:

Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

Here the COMPLETE code of my form :

public partial class Form1 : Form
{
    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern bool CreatePipe(out SafeFileHandle hReadPipe, out SafeFileHandle hWritePipe, SECURITY_ATTRIBUTES lpPipeAttributes, int nSize);

    [StructLayout(LayoutKind.Sequential)]
    public struct SECURITY_ATTRIBUTES
    {
        public DWORD nLength;
        public IntPtr lpSecurityDescriptor;
        public bool bInheritHandle;
    }

    public Form1()
    {
        InitializeComponent();
    }

    private void btCreate_Click(object sender, EventArgs e)
    {
        SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
        sa.nLength = (DWORD)Syste开发者_C百科m.Runtime.InteropServices.Marshal.SizeOf(sa);
        sa.lpSecurityDescriptor = IntPtr.Zero;
        sa.bInheritHandle = true;

        SafeFileHandle hWrite = null;
        SafeFileHandle hRead = null;

        if (CreatePipe(out hRead, out hWrite, sa, 4096))
        {
            MessageBox.Show("Pipe created !");
        }
        else
            MessageBox.Show("Error : Pipe not created !");
    }   
}

At the top I declare : using DWORD = System.UInt32;

Thank you very much if someone can help.


The reason for the protected memory violation is because the Windows API for CreatePipe was expecting a pointer value to an area of memory which the function would use as a spring board to the security attributes structure. Simply passing in the SECURITY_ATTRIBUTES structure would then overwrite secure memory (pages not yet allocated to your application), and hence the protected memory error.

Passing in an IntPtr to represent this pointer, solves your problem.

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern bool CreatePipe(ref IntPtr hReadPipe, ref IntPtr hWritePipe, IntPtr  lpPipeAttributes, int nSize);

    [StructLayout(LayoutKind.Sequential)]
    public struct SECURITY_ATTRIBUTES
    {
        public DWORD nLength;
        public IntPtr lpSecurityDescriptor;
        [MarshalAs(UnmanagedType.Bool)]
        public bool bInheritHandle;
    }

    public Form1()
    {
        InitializeComponent();
    }

    private void btnCreate_Click(object sender, EventArgs e)
    {

        SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
        sa.nLength = (DWORD)System.Runtime.InteropServices.Marshal.SizeOf(sa);
        sa.lpSecurityDescriptor = IntPtr.Zero;
        sa.bInheritHandle = true;

        IntPtr attr = Marshal.AllocHGlobal(Marshal.SizeOf(sa));
        Marshal.StructureToPtr(sa, attr, true);

        IntPtr hWrite = new IntPtr();
        IntPtr hRead = new IntPtr();

        if (CreatePipe(ref hRead, ref hWrite, attr, 4096))
        {
            MessageBox.Show("Pipe created !");
        }
        else
        {
            int error = Marshal.GetLastWin32Error();
            MessageBox.Show("Error : Pipe not created ! LastError= " + error);
        }
    }


Just change the declaration, so that SECURITY_ATTRIBUTES is a pointer:

public static extern bool CreatePipe(out SafeFileHandle hReadPipe, out SafeFileHandle hWritePipe, ref SECURITY_ATTRIBUTES lpPipeAttributes, int nSize);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜