File PartitionEntry.cs
codice:
using System;

/*
 * http://www.datarescue.com/laboratory/partition.htm
 * 
 * +OOh  	Partition State																1 byte
 * 				00h = non active
 * 				80h = Boot Partition 	
 * +01h 	Begin of partition : Head 													1 byte
 * +02h 	Begin of partition : Cylinder - Sector 										1 word	(0->5 sector | 6 -> 15 cylinder)
 * +04h 	Type of partition (see list) 												1 byte
 * +05h 	End of partition : Head 													1 byte
 * +06h 	End of partition : Cylinder - Sector 										1 word	(0->5 sector | 6 -> 15 cylinder)
 * +08h 	Number of sectors between the MBR and the 1st sector of the partition 		4 bytes
 * +0Ch 	Number of sectors in the partition 											4 bytes
 */

/**
 * 
 * Codici dei tipi delle partizioni
 *  
 *  0  Vuoto           1e  Hidden W95 FAT1 80  Vecchio Minix   be  Solaris boot
 *  1  FAT12           24  NEC DOS         81  Minix / vecchio bf  Solaris
 *  2  XENIX root      39  Plan 9          82  Linux swap / So c1  DRDOS/sec (FAT-
 *  3  XENIX usr       3c  Recupero Partit 83  Linux           c4  DRDOS/sec (FAT-
 *  4  FAT16 <32M      40  Venix 80286     84  C nascosto OS/2 c6  DRDOS/sec (FAT-
 *  5  Esteso          41  PPC PReP Boot   85  Linux esteso    c7  Syrinx
 *  6  FAT16           42  SFS             86  set volume NTFS da  Non-FS data
 *  7  HPFS/NTFS       4d  QNX4.x          87  set volume NTFS db  CP/M / CTOS / .
 *  8  AIX             4e  QNX4.x 2a parti 88  Linux plaintext de  Dell Utility
 *  9  AIX avviabile   4f  QNX4.x 3rd part 8e  Linux LVM       df  BootIt
 *  a  OS/2 Boot Manag 50  OnTrack DM      93  Amoeba          e1  accesso DOS
 *  b  W95 FAT32       51  OnTrack DM6 Aux 94  Amoeba BBT      e3  DOS R/O
 *  c  W95 FAT32 (LBA) 52  CP/M            9f  BSD/OS          e4   SpeedStor
 *  e  W95 FAT16 (LBA) 53  OnTrack DM6 Aux a0  Ibernazione IBM eb  BeOS fs
 *  f  W95 Ext'd (LBA) 54  OnTrackDM6      a5  FreeBSD         ee  EFI GPT
 * 10  OPUS            55   EZ-Drive       a6  OpenBSD         ef  EFI (FAT-12/16/
 * 11  FAT12 nascosto  56  Golden Bow      a7  NeXTSTEP        f0  Linux/PA-RISC b
 * 12  Diagnostica Com 5c  Priam Edisk     a8  Darwin UFS      f1   SpeedStor
 * 14  FAT16 nascosto  61   SpeedStor      a9  NetBSD          f4   SpeedStor
 * 16  FAT16 nascosto  63  GNU HURD o SysV ab  Darwin boot     f2  DOS secondario
 * 17  HPFS/NTFS nasco 64  Novell Netware  b7  BSDI fs         fd  Autorilevamento
 * 18  AST SmartSleep  65  Novell Netware  b8  BSDI swap       fe  LANstep
 * 1b  Hidden W95 FAT3 70  DiskSecure Mult bb  Boot Wizard hid ff  BBT
 * 1c  Hidden W95 FAT3 75  PC/IX
 * 
 */

namespace PHPSoft.DiskAnalyzer
{
	public enum PartitionType
	{
		Empty					= 0x00,
		FAT12					= 0x01,
		XENIX_Root				= 0x02,
		XENIX_User				= 0x03,
		FAT16_32MB				= 0x04,
		Extended				= 0x05,
		FAT16					= 0x06,
		HPFS_NTFS				= 0x07,
		AIX						= 0x08,
		AIX_Bootable			= 0x09,
		OS2_BootManager			= 0x0a,
		Win95_FAT32				= 0x0b,
		Win95_FAT32_LBA			= 0x0c,
		Win95_FAT16_LBA			= 0x0e,
		Win95_Extended_LBA		= 0x0f,
		OPUS					= 0x10,
		FAT12_Hidden			= 0x11,
		Diagnostic				= 0x12,
		FAT16_Hidden_Sectored	= 0x14,
		FAT16_Hidden			= 0x16,
		HPFS_NTFS_Hidden		= 0x17,
		AST_SmartSleep			= 0x18,
		Win95_FAT32_Hidden		= 0x1b,
		Win95_FAT32_LBA_Hidden	= 0x1c,
		Win95_FAT16_LBA_Hidden	= 0x1e,
		NEC_DOS					= 0x24,
		NOS						= 0x32,
		JFS_OS2					= 0x35,
		Plan9					= 0x39,
		PartitionMagic_Recovery	= 0x3c,
		NetWare_Hidden			= 0x3d,
		Venix_80286				= 0x40,
		PPC_PReP_Boot			= 0x41,
		SFS						= 0x42,
		QNX4					= 0x4d,
		QNX4_Second				= 0x4e,
		QNX4_Third				= 0x4f,
		OnTrack_DiskManager_RO	= 0x50,
		OnTrack_DiskManager_RW	= 0x51,
		CP_M					= 0x52,
		OnTrack_DiskManager_AUX	= 0x53,
		OnTrack_DiskManager_DDO	= 0x54,
		EZDrive					= 0x55,
		GoldenBow				= 0x56,
		PriamEdisk				= 0x5c,
		SpeedStor				= 0x61,
		Hurd					= 0x63,
		Novell_Netware_286		= 0x64,
		Novell_Netware_386		= 0x65,
		DiskSecure_MultiBoot	= 0x70,
		PC_IX					= 0x75,
		Minix_Old				= 0x80
	}

	public struct DataZone
	{
		uint start;
		uint end;

		public DataZone(uint start, uint end)
		{
			this.start = start;
			this.end = end;
		}

		public uint Start
		{
			get
			{
				return start;
			}
		}

		public uint End
		{
			get
			{
				return end;
			}
		}
	}

	/// <summary>
	/// Descrizione di riepilogo per PartitionEntry.
	/// </summary>
	public class PartitionEntry
	{
		int number;
		bool active;
		DataZone head;
		DataZone cylinder;
		DataZone sector;
		int sectorsBetweenMBRandPartition;
		int sectorsInPartition;
		PartitionType type;

		public PartitionEntry(int PartitionNumber, byte[] MBRBuffer, int StartingPosition)
		{
			#region Imposta il numero della partizione
			this.number = PartitionNumber;
			#endregion

			#region Verifica se la partizione è attiva o meno
			if (MBRBuffer[StartingPosition + 0x00] == 0x80)
			{
				this.active = true;
			}
			else
			{
				this.active = false;
			}
			#endregion

			#region Acquisisce l'inizio e la fine in cilindri/settori della partizione
			uint cylSecStart = BitConverter.ToUInt16(MBRBuffer, StartingPosition + 0x02);
			uint cylSecEnd = BitConverter.ToUInt16(MBRBuffer, StartingPosition + 0x06);
/*
			this.cylinder = new DataZone(
				MBRBuffer[StartingPosition + 0x02] | ((MBRBuffer[StartingPosition + 0x03] & 0xC0) ) ,
				MBRBuffer[StartingPosition + 0x06],
				);
*/
			this.sector = new DataZone(
				cylSecStart & 0x3F,
				cylSecEnd & 0x3F);
			#endregion

			#region Acquisisce il tipo di partizione
			this.type = (PartitionType)MBRBuffer[StartingPosition + 0x04];
			#endregion
		}

		public int Number
		{
			get
			{
				return number;
			}
		}

		public bool Active
		{
			get
			{
				return active;
			}
		}

		public DataZone Head
		{
			get
			{
				return head;
			}
		}

		public DataZone Cylinder
		{
			get
			{
				return cylinder;
			}
		}

		public DataZone Sector
		{
			get
			{
				return sector;
			}
		}

		public int SectorsBetweenMBRandPartition
		{
			get
			{
				return sectorsBetweenMBRandPartition;
			}
		}

		public int SectorsInPartition
		{
			get
			{
				return sectorsInPartition;
			}
		}

		public PartitionType Type
		{
			get
			{
				return type;
			}
		}

	}
}
Il codice postato è estremamente semplice, se si è letto con attenzione quanto scritto prima, soprattutto il file PartitionEntry contiene proprietà ed enumerazioni perché tutto il lavoro di parsing della struttura viene eseguito nel costruttore

Mentre PartitionTable.cs si limita a leggere tutto e fare il ciclo for che legge le 4 righe della tabella delle partizioni ed il gioco è fatto

Cosa manca da implementare?
- Il check sull'mbr per verificarne la correttezza della struttura
- Il supporto per le partizioni estese
- Completare la lettura delle informazioni sulla partizione
- Completare l'elenco del tipi di partizione

Come si usa la PartitionTable.cs? In modo infinitamente semplice ...

codice:
			this.partitionListbox.Items.Clear();

			PartitionTable pTable = new PartitionTable(this.textBox1.Text);

			foreach(PartitionEntry pEntry in pTable.PartitionEntries)
			{
				this.partitionListbox.Items.Add("Partition " + pEntry.Number.ToString());
				this.partitionListbox.Items.Add("\tType:" + pEntry.Type.ToString());
				this.partitionListbox.Items.Add("\tPartition Size:");
				this.partitionListbox.Items.Add("\t\tStart: 0/0/" + pEntry.Sector.Start.ToString());
				this.partitionListbox.Items.Add("\t\tEnd: 0/0/" + pEntry.Sector.End.ToString());
				this.partitionListbox.Items.Add("");
			}
		}
come potete vedere basta inizializzare la classe passandoli il percorso (in questo caso è contenuto nella textbox1 nel form) e poi ciclare le varie entries della lista restituita ... basta

Spero che sia interessante per qualcuno!

ciauuuuuu