I have successfully created 2 or more partitions in USB drive using DeviceIoControl in C++. Now I am trying to convert this code into C# using kernel32 and DeviceIoControl. But I am not getting more than 1 partition. Can anybody tell me what is wrong with this code?
Environment using is Windows 8.1, Visual Studio 2013
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace PartitionWrapper
{
public class IOWrapper
{
public static bool CreatePartitions(string selectedDrive)
{
bool RetCode = false;
try
{
bool bSuccess = false;
uint dwBytesReturned = 0;
IntPtr hDisk = OpenVolume(selectedDrive);
if (hDisk == null || hDisk == FSConstants.INVALID_HANDLE_VALUE)
{
RetCode = false;
goto FINAL;
}
bSuccess = FSStructures.DeviceIoControl(hDisk, FSConstants.IOCTL_DISK_DELETE_DRIVE_LAYOUT, IntPtr.Zero, 0, default(IntPtr), default(uint), ref dwBytesReturned);
// Get the partition information
uint PartitionInfomations = (uint)(Marshal.SizeOf(typeof(FSStructures.DRIVE_LAYOUT_INFORMATION_EX)) + 3 * Marshal.SizeOf(typeof(FSStructures.PARTITION_INFORMATION_EX)));
byte DBuffer = new byte[PartitionInfomations];
GCHandle handle = GCHandle.Alloc(DBuffer, GCHandleType.Pinned);
FSStructures.DRIVE_LAYOUT_INFORMATION_EX pDriveLayout = (FSStructures.DRIVE_LAYOUT_INFORMATION_EX)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(FSStructures.DRIVE_LAYOUT_INFORMATION_EX));
IntPtr pDriveLayoutPtr = Marshal.AllocHGlobal(Marshal.SizeOf(pDriveLayout));
Marshal.StructureToPtr(pDriveLayout, pDriveLayoutPtr, false);
// bSuccess = FSStructures.DeviceIoControl(hDisk, FSConstants.IOCTL_DISK_GET_DRIVE_LAYOUT_EX, default(IntPtr), default(uint), pDriveLayoutPtr, PartitionInfomations, ref dwBytesReturned);
pDriveLayout = (FSStructures.DRIVE_LAYOUT_INFORMATION_EX)Marshal.PtrToStructure(pDriveLayoutPtr, typeof(FSStructures.DRIVE_LAYOUT_INFORMATION_EX));
if (bSuccess || dwBytesReturned != PartitionInfomations)
{
RetCode = true;
}
else { RetCode = false; goto FINAL; }
pDriveLayout.PartitionEntry = new FSStructures.PARTITION_INFORMATION_EX[0x16];
pDriveLayout.PartitionStyle = FSStructures.PARTITION_STYLE.MasterBootRecord;
pDriveLayout.PartitionCount = 4;
pDriveLayout.DriveLayoutInformatiton.Mbr.Signature = 0xA4B57300;
pDriveLayout.PartitionEntry[0] = new FSStructures.PARTITION_INFORMATION_EX();
pDriveLayout.PartitionEntry[0].PartitionStyle = FSStructures.PARTITION_STYLE.MasterBootRecord;
pDriveLayout.PartitionEntry[0].Mbr.BootIndicator = true;
pDriveLayout.PartitionEntry[0].Mbr.RecognizedPartition = true;
pDriveLayout.PartitionEntry[0].Mbr.PartitionType = 0x0B;
pDriveLayout.PartitionEntry[0].PartitionNumber = 1;
pDriveLayout.PartitionEntry[0].StartingOffset = 32256;
pDriveLayout.PartitionEntry[0].PartitionLength = 3221225472;
pDriveLayout.PartitionEntry[0].RewritePartition = true;
pDriveLayout.PartitionEntry[0].Mbr.HiddenSectors = 32256 / 512;
pDriveLayout.PartitionEntry[1] = new FSStructures.PARTITION_INFORMATION_EX();
pDriveLayout.PartitionEntry[1].PartitionStyle = FSStructures.PARTITION_STYLE.MasterBootRecord;
pDriveLayout.PartitionEntry[1].Mbr.BootIndicator = false;
pDriveLayout.PartitionEntry[1].Mbr.RecognizedPartition = true;
pDriveLayout.PartitionEntry[1].Mbr.PartitionType = 0x0B;
pDriveLayout.PartitionEntry[1].PartitionNumber = 2;
pDriveLayout.PartitionEntry[1].StartingOffset = 32256 + 3221225472;
pDriveLayout.PartitionEntry[1].PartitionLength = 2147483648; //2147483648;//3221225472;
pDriveLayout.PartitionEntry[1].RewritePartition = true;
pDriveLayout.PartitionEntry[1].Mbr.HiddenSectors = 32256 / 512;
for (int i = 0; i < pDriveLayout.PartitionEntry.Length; i++)
{
pDriveLayout.PartitionEntry[i].RewritePartition = true;
}
try
{
bSuccess = FSStructures.DeviceIoControl(hDisk, FSConstants.IOCTL_DISK_SET_DRIVE_LAYOUT_EX, ref pDriveLayout, PartitionInfomations, default(IntPtr), default(uint), ref dwBytesReturned);
}
catch (Exception ex)
{
}
if (bSuccess)
{
RetCode = true;
}
else { RetCode = false; }
bSuccess = FSStructures.DeviceIoControl(hDisk, FSConstants.IOCTL_DISK_UPDATE_PROPERTIES, IntPtr.Zero, 0, default(IntPtr), default(uint), ref dwBytesReturned);
if (bSuccess)
{
RetCode = true;
}
else { RetCode = false; }
//}
FINAL:
// Close the disk handle.
if (hDisk != null && hDisk != FSConstants.INVALID_HANDLE_VALUE)
{
FSStructures.CloseHandle(hDisk);
}
}
catch { return false; }
return RetCode;
}
private static IntPtr OpenVolume(string DeviceName)
{
try
{
IntPtr hDevice;
hDevice = FSStructures.CreateFile(
@"\." + DeviceName,
FSConstants.GENERIC_EXECUTE | FSConstants.GENERIC_READ | FSConstants.GENERIC_WRITE | FSConstants.FILE_SHARE_READ | FSConstants.FILE_SHARE_WRITE,
FSConstants.FILE_SHARE_WRITE,
IntPtr.Zero,
FSConstants.OPEN_EXISTING,
0,
IntPtr.Zero);
if ((int)hDevice == -1)
{
throw new Exception(Marshal.GetLastWin32Error().ToString());
}
return hDevice;
}
catch { return FSConstants.INVALID_HANDLE_VALUE; }
}
internal static class FSConstants
{
public const uint FILE_SHARE_READ = 0x00000001;
public const uint FILE_SHARE_WRITE = 0x00000002;
public const uint OPEN_EXISTING = 3;
public const int GENERIC_EXECUTE = 0x10000000;
public const uint GENERIC_READ = (0x80000000);
public const uint GENERIC_WRITE = (0x40000000);
public static IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
public const uint IOCTL_DISK_GET_DRIVE_LAYOUT_EX = 0x00070050;
public const uint IOCTL_DISK_SET_DRIVE_LAYOUT_EX = 0x7C054;
public const int IOCTL_DISK_UPDATE_PROPERTIES = 0x70140;
public const int IOCTL_DISK_DELETE_DRIVE_LAYOUT = 0x0007c010;
public const int IOCTL_DISK_CREATE_DISK = 0x7C058;
}
internal static class FSStructures
{
[DllImport(“kernel32.dll”, EntryPoint = “CreateFile”, SetLastError = true)]
public static extern IntPtr CreateFile(
string lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
IntPtr lpSecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplateFile);
[DllImport(“kernel32.dll”, SetLastError = true)]
public static extern int CloseHandle(IntPtr hObject);
[DllImport(“kernel32.dll”, SetLastError = true)]
public static extern bool DeviceIoControl(
IntPtr hDevice,
uint dwIoControlCode,
[Optional]ref DRIVE_LAYOUT_INFORMATION_EX lpInBuffer,
uint nInBufferSize,
[Optional] [Out] IntPtr lpOutBuffer,
uint nOutBufferSize,
[Optional] ref uint lpBytesReturned,
[Optional] IntPtr lpOverlapped);
[DllImport(“kernel32.dll”, SetLastError = true)]
public static extern bool DeviceIoControl(
IntPtr hDevice,
uint dwIoControlCode,
IntPtr lpInBuffer,
uint nInBufferSize,
[Optional] [Out] IntPtr lpOutBuffer,
uint nOutBufferSize,
[Optional] ref uint lpBytesReturned,
[Optional] IntPtr lpOverlapped);
[StructLayout(LayoutKind.Sequential)]
public struct DRIVE_LAYOUT_INFORMATION_EX
{
public PARTITION_STYLE PartitionStyle;
public int PartitionCount;
public DRIVE_LAYOUT_INFORMATION_UNION DriveLayoutInformatiton;
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 0x16)]
public PARTITION_INFORMATION_EX PartitionEntry;
}
[StructLayout(LayoutKind.Sequential)]
public struct PARTITION_INFORMATION_EX
{
[MarshalAs(UnmanagedType.U4)]
public PARTITION_STYLE PartitionStyle;
public long StartingOffset;
public long PartitionLength;
public int PartitionNumber;
public bool RewritePartition;
public PARTITION_INFORMATION_MBR Mbr;
public PARTITION_INFORMATION_GPT Gpt;
}
[StructLayout(LayoutKind.Sequential)]
public struct PARTITION_INFORMATION_MBR
{
public byte PartitionType;
[MarshalAs(UnmanagedType.U1)]
public bool BootIndicator;
[MarshalAs(UnmanagedType.U1)]
public bool RecognizedPartition;
public uint HiddenSectors;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct PARTITION_INFORMATION_GPT
{
public Guid PartitionType;
public Guid PartitionId;
[MarshalAs(UnmanagedType.U8)]
public EFIPartitionAttributes Attributes;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 36)]
public string Name;
}
[Flags]
public enum EFIPartitionAttributes : ulong
{
GPT_ATTRIBUTE_PLATFORM_REQUIRED = 0x0000000000000001,
LegacyBIOSBootable = 0x0000000000000004,
GPT_BASIC_DATA_ATTRIBUTE_NO_DRIVE_LETTER = 0x8000000000000000,
GPT_BASIC_DATA_ATTRIBUTE_HIDDEN = 0x4000000000000000,
GPT_BASIC_DATA_ATTRIBUTE_SHADOW_COPY = 0x2000000000000000,
GPT_BASIC_DATA_ATTRIBUTE_READ_ONLY = 0x1000000000000000
}
[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_GPT
{
public Guid DiskId;
public long StartingUsableOffset;
public long UsableLength;
public int MaxPartitionCount;
}
[StructLayout(LayoutKind.Sequential)]
public struct DRIVE_LAYOUT_INFORMATION_MBR
{
public uint Signature;
}
public enum PARTITION_STYLE : int
{
MasterBootRecord = 0,
GuidPartitionTable = 1,
Raw = 2
}
}
}
}