c# - 为什么我的 C#/pinvoke DeviceIoControl 调用返回 0 字节读取垃圾数据?

标签 c# deviceiocontrol

我有一个运行良好的非托管 C++ Windows 控制台应用程序。我想要它在 C# 中。我已经为必要的 Kernel32.dll 符号完成了 DllImport 语句:

[StructLayout(LayoutKind.Sequential)]
internal struct DiskGeometry
{
    public long Cylinders;
    public int MediaType;
    public int TracksPerCylinder;
    public int SectorsPerTrack;
    public int BytesPerSector;
}

internal static class NativeMethods
{
    internal const uint FileAccessGenericRead = 0x80000000;
    internal const uint FileShareWrite = 0x2;
    internal const uint FileShareRead = 0x1;
    internal const uint CreationDispositionOpenExisting = 0x3;
    internal const uint IoCtlDiskGetDriveGeometry = 0x70000;

    [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    public static extern SafeFileHandle CreateFile(
        string fileName,
        uint fileAccess,
        uint fileShare,
        IntPtr securityAttributes,
        uint creationDisposition,
        uint flags,
        IntPtr template);

    [DllImport("Kernel32.dll", SetLastError = false, CharSet = CharSet.Auto)]
    public static extern int DeviceIoControl(
        SafeFileHandle device,
        uint controlCode,
        IntPtr inBuffer,
        uint inBufferSize,
        IntPtr outBuffer,
        uint outBufferSize,
        ref uint bytesReturned,
        IntPtr overlapped);
}

然后我有以下应用程序代码:

    public static void Main()
    {
        SafeFileHandle diskHandle = NativeMethods.CreateFile(
            "\\\\.\\PhysicalDrive0",
            NativeMethods.FileAccessGenericRead,
            NativeMethods.FileShareWrite | NativeMethods.FileShareRead,
            IntPtr.Zero,
            NativeMethods.CreationDispositionOpenExisting,
            0,
            IntPtr.Zero);
        if (diskHandle.IsInvalid)
        {
            Console.WriteLine("CreateFile failed with error: {0}", Marshal.GetLastWin32Error());
            return;
        }

        int geometrySize = Marshal.SizeOf(typeof(DiskGeometry));
        Console.WriteLine("geometry size = {0}", geometrySize);

        IntPtr geometryBlob = Marshal.AllocHGlobal(geometrySize);

        uint numBytesRead = 0;
        if (0 == NativeMethods.DeviceIoControl(
            diskHandle,
            NativeMethods.IoCtlDiskGetDriveGeometry,
            IntPtr.Zero,
            0,
            geometryBlob,
            (uint)geometrySize,
            ref numBytesRead,
            IntPtr.Zero))
        {
            Console.WriteLine("DeviceIoControl failed with error: {0}", Marshal.GetLastWin32Error());
            return;
        }

        Console.WriteLine("Bytes read = {0}", numBytesRead);

        DiskGeometry geometry = (DiskGeometry)Marshal.PtrToStructure(geometryBlob, typeof(DiskGeometry));
        Marshal.FreeHGlobal(geometryBlob);

        long bytesPerCylinder = (long)geometry.TracksPerCylinder * (long)geometry.SectorsPerTrack * (long)geometry.BytesPerSector;
        long totalSize = geometry.Cylinders * bytesPerCylinder;

        Console.WriteLine("Media Type:           {0}", geometry.MediaType);
        Console.WriteLine("Cylinders:            {0}", geometry.Cylinders);
        Console.WriteLine("Tracks per Cylinder:  {0}", geometry.TracksPerCylinder);
        Console.WriteLine("Sectors per Track:    {0}", geometry.SectorsPerTrack);
        Console.WriteLine("Bytes per Sector:     {0}", geometry.BytesPerSector);
        Console.WriteLine("Bytes per Cylinder:   {0}", bytesPerCylinder);
        Console.WriteLine("Total disk space:     {0}", totalSize);
    }

我的 C# 应用程序打印“读取的字节数 = 0”,并且几何成员值为垃圾。我当然不是 DllImport 和编码(marshal)处理方面的专家。请帮助我了解我做错了什么。如果我将 DeviceIoControl 的第五个参数更改为“ref DiskGeometry”并且只传入在调用之前创建的一个参数(而不是 IntPtr 和 alloc),则所有打印的几何体成员值为 0。

最佳答案

你打错了,试试这个:

internal const uint IoCtlDiskGetDriveGeometry = 0x70000;

关于c# - 为什么我的 C#/pinvoke DeviceIoControl 调用返回 0 字节读取垃圾数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13712212/

相关文章:

c# - 我如何将更多时间添加到 datetime.now 解析它然后重置回原始 datetime.now?

c# - WPF WebBrowser 控件中的 ckeditor

c# - 弹出式文本框双向绑定(bind)

C# 和 NPOI 无法读取数字和字符串值

c++ - DeviceIoControl 对内存位置的访问无效

c - 安装的 VHD 上的 FSCTL_LOCK_VOLUME 失败并出现 ERROR_ACCESS_DENIED

c# - C# 6 中的(提议的) “Record” 类是什么?

delphi - 如何正确检索电池序列号?

windows-8 - 硬盘序列号在 Windows XP、Vista 和 7 中每 2 个字节翻转一次,但在 Windows 8 中没有