/// <summary> /// Initializes a new instance of the <see cref="DevicePartition"/> class. /// </summary> /// <param name="partititonInformation">The partititon information.</param> internal DevicePartition(PARTITION_INFORMATION_EX partititonInformation) { this.PartitionStyle = partititonInformation.PartitionStyle.ConvertToString(); this.StartingOffset = partititonInformation.StartingOffset; this.PartitionLength = partititonInformation.PartitionLength; this.Number = Convert.ToInt32(partititonInformation.PartitionNumber); switch(partititonInformation.PartitionStyle) { case PARTITION_STYLE.PARTITION_STYLE_MBR: this.BootIndicator = partititonInformation.DriveLayoutInformaiton.Mbr.BootIndicator; this.PartitionType = partititonInformation.DriveLayoutInformaiton.Mbr.PartitionType.ConvertToString(); this.HiddenSectors = Convert.ToInt32(partititonInformation.DriveLayoutInformaiton.Mbr.HiddenSectors); break; case PARTITION_STYLE.PARTITION_STYLE_GPT: this.Name = partititonInformation.DriveLayoutInformaiton.Gpt.Name; this.GptId = partititonInformation.DriveLayoutInformaiton.Gpt.PartitionId; this.GptPartitionType = partititonInformation.DriveLayoutInformaiton.Gpt.PartitionType; this.GptAttributes = Convert.ToInt64(partititonInformation.DriveLayoutInformaiton.Gpt.Attributes); break; case PARTITION_STYLE.PARTITION_STYLE_RAW: break; } }
/// <summary> /// Gets the drive layout. /// This is special case DeviceIoControl call. The <see cref="DRIVE_LAYOUT_INFORMATION_EX"/> contains dynamic array /// </summary> /// <param name="device">The device to query</param> /// <remarks>Code was taken from: http://brianhehir.blogspot.co.il/2011/12/kernel32dll-deviceiocontrol-in-c.html </remarks> /// <returns><c>Tuple</c> of <see cref="DRIVE_LAYOUT_INFORMATION_EX"/> and array of <see cref="PARTITION_INFORMATION_EX"/></returns> internal Tuple <DRIVE_LAYOUT_INFORMATION_EX, PARTITION_INFORMATION_EX[]> GetDriveLayout(DeviceHandle device) { bool functionResult = false; IntPtr ptrInputData = IntPtr.Zero; int numberOfExpectedPartitions = 1; // 48 = the number of bytes in DRIVE_LAYOUT_INFORMATION_EX up to // the first PARTITION_INFORMATION_EX in the array. // And each PARTITION_INFORMATION_EX is 144 bytes. var structureSize = 48 + (numberOfExpectedPartitions * 144); int lpBytesReturned = 0; NativeOverlapped nativeOverlapped = new NativeOverlapped(); int win32Error = 0; try { // First try ptrInputData = Marshal.AllocHGlobal(structureSize); while (functionResult == false) { lock (lockMe) { IntPtr handle = device.OpenDeviceHandle(); functionResult = UnsafeNativeMethods.DeviceIoControl(handle, IoControlCode.IOCTL_DISK_GET_DRIVE_LAYOUT_EX, IntPtr.Zero, 0, ptrInputData, structureSize, ref lpBytesReturned, ref nativeOverlapped); win32Error = Marshal.GetLastWin32Error(); device.CloseDeviceHandle(); } if (functionResult == false) { if (win32Error == UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER) { Marshal.FreeHGlobal(ptrInputData); checked { numberOfExpectedPartitions++; structureSize = 48 + (numberOfExpectedPartitions * 144); } ptrInputData = Marshal.AllocHGlobal(structureSize); } else { throw new Win32Exception("Could not acquire information from windows kernel.", new Win32Exception(win32Error)); } } } DRIVE_LAYOUT_INFORMATION_EX driveLayoutInfo = default(DRIVE_LAYOUT_INFORMATION_EX); driveLayoutInfo = (DRIVE_LAYOUT_INFORMATION_EX)Marshal.PtrToStructure(ptrInputData, typeof(DRIVE_LAYOUT_INFORMATION_EX)); PARTITION_INFORMATION_EX[] partititons = new PARTITION_INFORMATION_EX[driveLayoutInfo.PartitionCount]; for (int iCounter = 0; iCounter < partititons.Length; iCounter++) { IntPtr partitionOffset = new IntPtr(ptrInputData.ToInt64() + 48 + (iCounter * 144)); partititons[iCounter] = (PARTITION_INFORMATION_EX)Marshal.PtrToStructure(partitionOffset, typeof(PARTITION_INFORMATION_EX)); } return(new Tuple <DRIVE_LAYOUT_INFORMATION_EX, PARTITION_INFORMATION_EX[]>(driveLayoutInfo, partititons)); } catch (Exception exp_gen) { throw new Win32Exception("Exception occurred while trying to work with Windows kernel", exp_gen); } finally { Marshal.FreeHGlobal(ptrInputData); } }