Marshal类的问题

时间:2010-11-24 22:25:30

标签: c# winforms winapi native import

我今天正在通过我的Win32课程来完成一些长期需要的改进。我被困在我的磁盘几何代码上。在

  

var ob =   (DiskGeometry)Marshal.PtrToStructure(geomp,   typeof(DiskGeometry));

行,它不断抛出异常..

  

尝试读取或写入受保护的内存。这通常表明其他内存已损坏。

我的代码是..

        if (Handle.IsInvalid)
        {
            Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
            return new DiskGeometry();
        }
        var geom = new DiskGeometry();
        var geomp = Marshal.AllocHGlobal(Marshal.SizeOf(geom));
        Marshal.StructureToPtr(geom, geomp, false);
        uint returnedBytes;
        if (!DeviceIoControl(Handle, (uint) IOCTL_CONTROL_CODE_CONSTANTS.IOCTL_DISK_GET_DRIVE_GEOMETRY, IntPtr.Zero, 0, ref geomp, (uint)Marshal.SizeOf(typeof(DiskGeometry)), out returnedBytes, IntPtr.Zero))
        {
            Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
            return new DiskGeometry();
        }
        var ob = (DiskGeometry)Marshal.PtrToStructure(geomp, typeof (DiskGeometry));

我做错了什么?

2 个答案:

答案 0 :(得分:0)

尝试这样的事情:

//you don't need to instantiate the managed type before this
var geomp = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(DiskGeometry)));

//remove this
Marshal.StructureToPtr(geom, geomp, false);

您只需要分配DiskIoControl将使用非托管类型填充的内存块。在指针引用该数据后,您将其编组为托管类型。

您还可以在致电Marshal.GetlastWin32Error()后查看ERROR_INSUFFICIENT_BUFFER DeviceIoControl,并确保returnedBytes == Marshal.SizeOf(typeof(DiskGeometry))

答案 1 :(得分:0)

当从非托管内存编组到托管内存时,“尝试读取或写入受保护的内存。这通常表示其他内存已损坏。”错误表明您没有访问在给定指针位置指定的内存位置的适当权限。

这些是用于验证代码工作正常的定义:

[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
        static extern bool DeviceIoControl(IntPtr hDevice, uint dwIoControlCode,
        IntPtr lpInBuffer, uint nInBufferSize,
        IntPtr lpOutBuffer, uint nOutBufferSize,
        out uint lpBytesReturned, IntPtr lpOverlapped);

(其他代码省略)

IntPtr Handle = CreateFile("\\\\.\\PhysicalDrive0", (EFileAccess)0, EFileShare.Read | EFileShare.Write, IntPtr.Zero, ECreationDisposition.OpenExisting, (EFileAttributes)0, IntPtr.Zero);

            var geom = new DiskGeometry();
            var geomp = Marshal.AllocHGlobal(Marshal.SizeOf(geom));
            uint returnedBytes = 0;

            Marshal.StructureToPtr(geom, geomp, false);

            if (!DeviceIoControl(Handle, (uint)IOCTL_DISK_GET_DRIVE_GEOMETRY, IntPtr.Zero, 0, geomp, 
                (uint)Marshal.SizeOf(typeof(DiskGeometry)), 
                out returnedBytes, 
                IntPtr.Zero))
            {
                Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
                return;
            }

            var ob = (DiskGeometry)Marshal.PtrToStructure(geomp, typeof(DiskGeometry));