Как создать раздел на жестком диске с помощью IOCTL_DISK_SET_DRIVE_LAYOUT на C # - PullRequest
1 голос
/ 29 февраля 2012

Мне нужно реализовать программу разметки жесткого диска, используя c #.Ниже приведена часть моего кода.

Я думаю, что он работает, потому что он возвращает true значение из DeviceIOcontrol без ошибок, но проблема в том, что моя программа ничего не показывает.

Я получил большую помощь от домашней страницы Medo, MSDN и сайта pinvoke.

public static bool partitionDisk(string path)
{
    var signature = new byte[4];
    System.Security.Cryptography.RandomNumberGenerator.Create().GetBytes(signature); 
    using (SafeFileHandle handle = NativeMethods2.CreateFile(path, (NativeMethods2.FILE_SHARE_READ|NativeMethods.GENERIC_READ ) | (NativeMethods.GENERIC_WRITE | NativeMethods2.FILE_SHARE_WRITE), 0, IntPtr.Zero, NativeMethods2.OPEN_EXISTING, 0, IntPtr.Zero))
    {
        if (handle.IsInvalid) { throw new Win32Exception(); }

        var newdi = new NativeMethods2.DRIVE_LAYOUT_INFORMATION_EX();

        newdi.PartitionStyle = NativeMethods2.PARTITION_STYLE.PARTITION_STYLE_MBR;
        newdi.PartitionCount = 4;
        newdi.DriveLayoutInformaiton.Mbr.Signature = BitConverter.ToInt32(signature, 0);

        newdi.PartitionEntry = new NativeMethods2.PARTITION_INFORMATION_EX[0x16];
        newdi.PartitionEntry[0] = new NativeMethods2.PARTITION_INFORMATION_EX();

        newdi.PartitionEntry[0].PartitionStyle = NativeMethods2.PARTITION_STYLE.PARTITION_STYLE_MBR;
        newdi.PartitionEntry[0].StartingOffset = 1048576; // check by diskpart
        newdi.PartitionEntry[0].PartitionLength = 0xFFFFFFFFFFfffff; //int64 max
        newdi.PartitionEntry[0].PartitionNumber = 1;
        newdi.PartitionEntry[0].RewritePartition = true;
        newdi.PartitionEntry[0].DriveLayoutInformaiton.Mbr.BootIndicator = false;
        newdi.PartitionEntry[0].DriveLayoutInformaiton.Mbr.HiddenSectors = 0; //sector size
        newdi.PartitionEntry[0].DriveLayoutInformaiton.Mbr.PartitionType = 0x07;// PARTITION_IFS (NTFS partition or logical drive)
        newdi.PartitionEntry[0].DriveLayoutInformaiton.Mbr.RecognizedPartition = true;

        for (int k = 2; k < newdi.PartitionCount; k++)
        {
            newdi.PartitionEntry[k] = new NativeMethods2.PARTITION_INFORMATION_EX();

            newdi.PartitionEntry[k].DriveLayoutInformaiton.Mbr.BootIndicator = false;
            newdi.PartitionEntry[k].DriveLayoutInformaiton.Mbr.HiddenSectors = 0;
            newdi.PartitionEntry[k].PartitionLength = 0;
            newdi.PartitionEntry[k].PartitionNumber = k;
            newdi.PartitionEntry[k].DriveLayoutInformaiton.Mbr.PartitionType = 0;
            newdi.PartitionEntry[k].DriveLayoutInformaiton.Mbr.RecognizedPartition = false;
            newdi.PartitionEntry[k].RewritePartition = true;
            newdi.PartitionEntry[k].StartingOffset = 0;
        }

        Int32 bytesOut = 0;
        if (NativeMethods2.DeviceIoControl(handle, NativeMethods2.IOCTL_DISK_SET_DRIVE_LAYOUT, ref newdi, Marshal.SizeOf(newdi), IntPtr.Zero, 0, ref bytesOut, IntPtr.Zero) == false) { throw new Win32Exception(); }
    }
}

private static class NativeMethods2
{
    public const int GENERIC_READ = -2147483648;
    public const int GENERIC_WRITE = 1073741824;
    public const int OPEN_EXISTING = 3;

    public const int FILE_SHARE_READ = 0x0000000001;
    public const int FILE_SHARE_WRITE = 0x0000000002; 

    public const int IOCTL_DISK_UPDATE_PROPERTIES = 0x70140;
    public const int IOCTL_DISK_SET_DRIVE_LAYOUT_EX = 0x7C054;

    public enum PARTITION_STYLE
    {
        PARTITION_STYLE_MBR = 0,
        PARTITION_STYLE_GPT = 1,
        PARTITION_STYLE_RAW = 2,
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct DRIVE_LAYOUT_INFORMATION_EX
    {
        public PARTITION_STYLE PartitionStyle;
        public int PartitionCount;
        public DRIVE_LAYOUT_INFORMATION_UNION DriveLayoutInformaiton;
        [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 0x16)]
        public PARTITION_INFORMATION_EX[] PartitionEntry;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct PARTITION_INFORMATION_EX
    {
        public PARTITION_STYLE PartitionStyle;
        public long StartingOffset;
        public long PartitionLength;
        public int PartitionNumber;
        public bool RewritePartition;
        public PARTITION_INFORMATION_UNION DriveLayoutInformaiton;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct PARTITION_INFORMATION_MBR
    {
        public byte PartitionType;
        public bool BootIndicator;
        public bool RecognizedPartition;
        public Int32 HiddenSectors;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct PARTITION_INFORMATION_GPT
    {
        public Guid PartitionType; //GUID
        public Guid PartitionId;   //GUID
        public Int64 Attributes;
        public char[] Name;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct PARTITION_INFORMATION
    {
        public long StartingOffset;
        public long PartitionLength;
        public int HiddenSectors;
        public int PartitionNumber;
        public byte PartitionType;
        [MarshalAs(UnmanagedType.I1)]
        public bool BootIndicator;
        [MarshalAs(UnmanagedType.I1)]
        public bool RecognizedPartition;
        [MarshalAs(UnmanagedType.I1)]
        public bool RewritePartition;
    }

    [StructLayout(LayoutKind.Explicit)]
    public struct DRIVE_LAYOUT_INFORMATION_UNION
    {
        [FieldOffset(0)]
        public DRIVE_LAYOUT_INFORMATION_MBR Mbr;

        [FieldOffset(0)]
        public DRIVE_LAYOUT_INFORMATION_GPT Gpt;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct DRIVE_LAYOUT_INFORMATION_MBR
    {
        public Int32 Signature;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct DRIVE_LAYOUT_INFORMATION_GPT
    {
        public Guid DiskId;
        public Int64 StartingUsableOffset;
        public Int64 UsableLength;
        public ulong MaxPartitionCount;
    }

    [StructLayout(LayoutKind.Explicit)]
    public struct PARTITION_INFORMATION_UNION
    {
        [FieldOffset(0)]
        public PARTITION_INFORMATION_MBR Mbr;
        [FieldOffset(0)]
        public PARTITION_INFORMATION_GPT Gpt;
    }

    [DllImportAttribute("kernel32.dll", EntryPoint = "CreateFileW", SetLastError = true)]
    public static extern SafeFileHandle CreateFile([MarshalAsAttribute(UnmanagedType.LPWStr)] string lpFileName, Int32 dwDesiredAccess, Int32 dwShareMode, IntPtr lpSecurityAttributes, Int32 dwCreationDisposition, Int32 dwFlagsAndAttributes, IntPtr hTemplateFile);

    [DllImportAttribute("kernel32.dll", EntryPoint = "DeviceIoControl", SetLastError = true)]
    [return: MarshalAsAttribute(UnmanagedType.Bool)]
    public static extern Boolean DeviceIoControl(SafeFileHandle hDevice, Int32 dwIoControlCode, ref DRIVE_LAYOUT_INFORMATION_EX lpInBuffer, int nInBufferSize, IntPtr lpOutBuffer, Int32 nOutBufferSize, ref Int32 lpBytesReturned, IntPtr lpOverlapped);
}

private static class NativeMethods
{
    public const int GENERIC_READ = -2147483648;
    public const int GENERIC_WRITE = 1073741824;
    public const int OPEN_EXISTING = 3;

    public const int IOCTL_DISK_CREATE_DISK = 0x7C058;

    public enum PARTITION_STYLE
    {
        PARTITION_STYLE_MBR = 0,
        PARTITION_STYLE_GPT = 1,
        PARTITION_STYLE_RAW = 2,
    }

    [StructLayoutAttribute(LayoutKind.Sequential)]
    public struct CREATE_DISK
    {
        public PARTITION_STYLE PartitionStyle;
        public CREATE_DISK_UNION_MBR_GPT MbrGpt;
    }

    [StructLayoutAttribute(LayoutKind.Explicit)]
    public struct CREATE_DISK_UNION_MBR_GPT
    {
        [FieldOffset(0)]
        public CREATE_DISK_MBR Mbr;
        [FieldOffset(0)]
        public CREATE_DISK_GPT Gpt;
    }

    [StructLayoutAttribute(LayoutKind.Sequential)]
    public struct CREATE_DISK_MBR
    {
        public Int32 Signature;
    }

    [StructLayoutAttribute(LayoutKind.Sequential)]
    public struct CREATE_DISK_GPT
    {
        public Guid DiskId;
        public Int32 MaxPartitionCount;
    }

    [DllImportAttribute("kernel32.dll", EntryPoint = "CreateFileW", SetLastError = true)]
    public static extern SafeFileHandle CreateFile([MarshalAsAttribute(UnmanagedType.LPWStr)] string lpFileName, Int32 dwDesiredAccess, Int32 dwShareMode, IntPtr lpSecurityAttributes, Int32 dwCreationDisposition, Int32 dwFlagsAndAttributes, IntPtr hTemplateFile);

    [DllImportAttribute("kernel32.dll", EntryPoint = "DeviceIoControl", SetLastError = true)]
    [return: MarshalAsAttribute(UnmanagedType.Bool)]
    public static extern Boolean DeviceIoControl(SafeFileHandle hDevice, Int32 dwIoControlCode, ref CREATE_DISK lpInBuffer, int nInBufferSize, IntPtr lpOutBuffer, Int32 nOutBufferSize, ref Int32 lpBytesReturned, IntPtr lpOverlapped);
}

... и для вызова функции:

DiskIO.partitionDisk("//./PHYSICALDRIVE2")

...