Visualizzazione dei risultati da 1 a 4 su 4
  1. #1

    [PILLOLA] Accessi al disco e gestione della tabella delle partizioni

    Hola a tutti,
    siccome è un'argomento abbastanza intricato sul quale sto sbattendo la testa da ieri per fare qualche esperimento con la tabella delle partizioni e la fat32/ntfs posto qua il codice necessario con delle spiegazioni!

    *** Accesso ai dischi

    [TEORIA]
    Windows NT e successivi, quindi windows 2000, windows XP e windows 2003, permettono l'accesso al disco fisico utilizzano le normali api utilizzate per la gestione dei file, ovvero CreateFile, CloseHandle, ReadFile, WriteFile e cosi via.
    Questo permette, soprattutto a chi ha confidenza con l'utilizzo di queste api, di essere infinitamente facilitato! Infatti al posto di mettere, ad esempio, come path c:\file_da_leggere.xyz si mette la path UNC relativa all'harddisk o alla partizione ed è possibile accederci per leggere e modificare il contenuto.
    Cosa sono le path UNC? Sono path particolari che permettono di accedere a tutti gli oggetti disponibili nel sistema, ovvero computer remoti, harddisk, partizioni, named pipes, periferiche usb, drivers che espongono un'oggetto e cosi via.
    Utilizzandole, tramite createfile, è possibile fare tutto e di più! Ovviamente è necessario avere un minimo di conoscenze per potersi muovere in questo campo.
    Purtroppo non è possibile utilizzare il .NET direttamente per accedere ai dischi perché non permette di utilizzare le path UNC e FileStream, anche se supporta gli handle, va ad eseguire operazioni non supportate dai dischi o da altre periferiche in generale quindi è necessario utilizzare direttamente le api

    [CODICE]
    Il codice è relativamente semplice è l'ho assemblato prendendolo da pinvoke, msdn e qualche modifichetta mia di piccola portata.

    codice:
    	#region Win32 IO Enumerations
    	[Flags]
    	public enum FileAccess : uint
    	{
    		GenericRead = 0x80000000,
    		GenericWrite = 0x40000000,
    		GenericExecute = 0x20000000,
    		GenericAll = 0x10000000,
    	}
    
    	[Flags]
    	public enum FileShare : uint
    	{
    		None = 0x00000000,
    		Read = 0x00000001,
    		Write = 0x00000002,
    		Delete = 0x00000004,
    	}
    
    	public enum CreationDisposition : uint
    	{
    		New = 1,
    		CreateAlways = 2,
    		OpenExisting = 3,
    		OpenAlways = 4,
    		TruncateExisting = 5,
    	}
    
    	[Flags]
    	public enum FileAttributes : uint
    	{
    		Readonly = 0x00000001,
    		Hidden = 0x00000002,
    		System = 0x00000004,
    		Directory = 0x00000010,
    		Archive = 0x00000020,
    		Device = 0x00000040,
    		Normal = 0x00000080,
    		Temporary = 0x00000100,
    		SparseFile = 0x00000200,
    		ReparsePoint = 0x00000400,
    		Compressed = 0x00000800,
    		Offline= 0x00001000,
    		NotContentIndexed = 0x00002000,
    		Encrypted = 0x00004000,
    		Write_Through = 0x80000000,
    		Overlapped = 0x40000000,
    		NoBuffering = 0x20000000,
    		RandomAccess = 0x10000000,
    		SequentialScan = 0x08000000,
    		DeleteOnClose = 0x04000000,
    		BackupSemantics = 0x02000000,
    		PosixSemantics = 0x01000000,
    		OpenReparsePoint = 0x00200000,
    		OpenNoRecall = 0x00100000,
    		FirstPipeInstance = 0x00080000
    	}
    	#endregion
    
    	/// <summary>
    	/// Descrizione di riepilogo per IOWin32Helper.
    	/// </summary>
    	public class IOWin32Helper
    	{
    		#region Win32 IO DllImport
    		[DllImport("kernel32", SetLastError = true)]
    		static extern unsafe System.IntPtr CreateFile
    		(
    			string FileName,							// file name
    			FileAccess DesiredAccess,					// access mode
    			FileShare ShareMode,						// share mode
    			IntPtr SecurityAttributes,					// Security Attributes
    			CreationDisposition CreationDisposition,	// how to create
    			FileAttributes FlagsAndAttributes,			// file attributes
    			IntPtr hTemplateFile						// handle to template file
    		);
    
    		[DllImport("kernel32", SetLastError = true)]
    		static extern unsafe bool ReadFile
    		(
    			IntPtr hObject,								// handle to file
    			void* pBuffer,								// data buffer
    			int NumberOfBytesToRead,					// number of bytes to read
    			int* pNumberOfBytesRead,					// number of bytes read
    			int Overlapped								// overlapped buffer
    		);
    
    		[DllImport("kernel32", SetLastError = true)]
    		static extern unsafe bool WriteFile
    		(
    			IntPtr hObject,								// handle to file
    			void* pBuffer,								// data buffer
    			int NumberOfBytesToWrite,					// number of bytes to write
    			int* pNumberOfBytesWritten,					// number of bytes written
    			int Overlapped								// overlapped buffer
    		);
    
    		[DllImport("kernel32", SetLastError = true)]
    		static extern unsafe bool CloseHandle
    		(
    			IntPtr hObject								// handle to object
    		);
    		#endregion
    
    		public static unsafe IntPtr Create(string FileName, FileAccess FileAccess, FileShare FileShare, CreationDisposition CreationDisposition, FileAttributes FileAttributes)
    		{
    			// Apre il file in base ai parametri richiesti
    			IntPtr handle = IOWin32Helper.CreateFile(FileName, FileAccess, FileShare, IntPtr.Zero, CreationDisposition, FileAttributes, IntPtr.Zero);
    
    			// Verifica se l'operazione è riuscita
    			if (handle == IntPtr.Zero)
    			{
    				// Lancia un'eccezione
    				Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
    			}
    
    			// Restituisce il puntatore
    			return handle;
    		}
    
    		public static unsafe int Read(IntPtr hObject, byte[] Buffer, int Index, int Count)
    		{
    			// Bytes letti
    			int readBytes = 0;
    
    			// Acquisisce il puntatore del buffer
    			fixed (byte* pBuffer = Buffer)
    			{
    				// Legge id ati
    				if (ReadFile(hObject, pBuffer + Index, Count, &readBytes, 0) == false)
    				{
    					// Lancia un'eccezione dato che l'operazione è fallita
    					Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
    				}
    			}
    
    			// Restituisce il numero di bytes letti
    			return readBytes;
    		}
    
    		public static unsafe int Write(IntPtr hObject, byte[] Buffer, int Index, int Count)
    		{
    			// Bytes letti
    			int writtenBytes = 0;
    
    			// Acquisisce il puntatore del buffer
    			fixed (byte* pBuffer = Buffer)
    			{
    				// Scrive i dati
    				if (WriteFile(hObject, pBuffer + Index, Count, &writtenBytes, 0) == false)
    				{
    					// Lancia un'eccezione dato che l'operazione è fallita
    					Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
    				}
    			}
    
    			// Restituisce il numero di bytes letti
    			return writtenBytes;
    		}
    
    		public static unsafe bool Close(IntPtr hObject)
    		{
    			// Chiude l'handle
    			return CloseHandle(hObject);
    		}
    	}
    Buona parte del codice postato sono dichiarazioni varie. Il codice vero e proprio è verso la fine e per la precisione, al momento, sono 4 metodi che si riferiscono a 4 API. A breve ne aggiungerò altre per spostare il puntatore, altrimenti non si ci può spostare, ad esempio, a inizio partizione o altro ... in pratica va implementato il Seek

    L'unico codice che spiego sarà quello di ReadFile e WriteFile perché CloseHandle è lampante e CreateFile lo è pure se è stato usato, almeno un po, il namespace System.IO ovvero se si ha lavorato con i file

    ReadFile e WriteFile sono identiche ma fanno, ovviamente, due operazioni ben distinte: la prima legge dei dati dall'handler passato e li scrive, per la lunghezza richiesta, nel puntatore passato restituendo il numero di byte letti, mentre la seconda scrive i byte passati nel puntatore sul disco per il numero di byte richiesti restituendo il numero di byte effettivamente scritti. Entrambe iniziano a lavorare dalla posizione corrente che all'inizio è ZERO e siccome a noi interessa partire da zero per leggere il primo settore del disco questo ci sta più che bene!

    IMPORTANTISSIMO: va eseguita una lettura/scrittura "allineata" con i settori del disco quando si lavora con queste periferiche! Ovvero vanno SEMPRE letti e SEMPRE scritti 512 byte altrimenti scoppia tutto (Si un settore è di 512 byte e le dimensioni dei cluster sono multipli di 512 per questo motivo, altrimenti fare i calcoli corretti ad ogni scrittura/lettura sarebbe troppo pesante ed il numero di operazioni sarebbe parecchio elevato!). Ovviamente anche quando si ci sposta si ci sposta allineandosi ai settori! Anche per questo motivo all'interno dell'MBR dei dischi non ci sta scritto la posizione in byte di inizio e fine partizione ma la posizione in facce, cilindri e settori (applicando una formuletta si ottiene la posizione sul disco ... anche se qua poi entra in ballo pure la gestione dell'LBA e quindi la cosa un po cambia ma questo è un'altro discorso)

    Questo ci permette quindi di fare
    [/CODE]
    Quanto spiegato fino ad adesso ci permette di fare
    IntPtr diskHandle = IOWin32Helper.Create(
    Disk,
    FileAccess.GenericRead,
    FileShare.Read | FileShare.Write,
    CreationDisposition.OpenExisting,
    FileAttributes.Device | FileAttributes.NoBuffering | FileAttributes.Write_Through);
    [/CODE]

    accedendo instantaneamente al disco in sola lettura, permettendo ad altri applicativi di leggere e scrivere, forzando ad aprire un'elemento già esistente senza crearlo in caso di assenza e per finire dicendogli che il "file" o oggetto in questione è una Device, non deve usare il buffering e deve quindi scrivere immediatamente sul disco (anche se quest'ultima opzione non ci interessa dato che non dobbiamo scrivere)

    continua...
    The fastest Redis alternative ... cachegrand! https://github.com/danielealbano/cachegrand

  2. #2
    *** MBR

    A questo punto siamo in grado di accedere alla tabella delle partizioni per poter leggere ed eventualmente scrivere le informazioni che vogliamo

    [TEORIA]
    L'MBR, o il Master Boot Record, è la prima cosa che il bios legge sul disco di avvio (ovvero il disco impostato nel bios come disco di boot. Comunque i bios moderni supportano più dischi di boot da leggere in sequenza).

    Esso contiene 5 elementi:
    - Nei primi 446 byte ci sta il boot loader del sistema scritto ovviamente in assembler e fatto in modo da utilizzare solamente le funzioni del bios per eseguire le operazioni di lettura/scrittura. I boot loader moderni, in realtà, passano la palla poi ad un modulo che effettivametne dopo che viene caricato prende il controllo questo perché 446 byte sono decisamente pochi

    - I 4 elementi successivi sono le 4 partizioni standard supportate dall'mbr ed ogni riga di questa tabella è composta da 16 byte nelle quali stanno le informazioni sulla partizione come la locazione sul disco, il tipo di partizione, se è avviabile o meno (nel caso di boot loader anche sulla partizione invece che sull'mbr del disco) e cosi via

    Il boot loader nell'mbr non ci interessa in alcun modo quindi possiamo tranquillamente scartarlo mentre i 4 elementi successivi ci interessano e come!

    La struttura è la seguente:
    codice:
    Posizione           Descrizione                                                                 Dimensione
    
    0x00                Stato della partizione (00h=Inattiva, 80h=Attiva)                           1 Byte
    0x01                Inizio della partizione - Facce                                             1 Byte
    0x02                Inizio della partizione - Cilindri/Settori                                  1 Word
    0x04                Tipo di partizione                                                          1 Byte
    0x05                Fine della partizione - Facce                                               1 Byte
    0x06                Fine della partizione - Cilindri/Settori                                    1 Word
    0x08                Numero di settori tra l'mbr e il primo settore della partizione             1 Double Word
    0x0C                Numero di settori nella partizione                                          1 Double Word
    Un byte corrisponde ad un byte ... un word corrisponde ad un valore unsigned composto da 2 byte, quindi a 16bit, ovvero UInt16, e per finire un double word corrisponde a due unsigned word quindi ad un valore composto da 4 byte e quindi un UInt32 o uint

    Come possiamo quindi leggere dalla partizione le informazioni che ci interessano? In maniera molto semplice, ovvero:
    - Accediamo al disco, tramite le path UNC, utilizzando \\.\PhysicalDriveX (dove X corrisponde al disco ... partendo da zero a tutti quelli connessi. Per vedere il numero di un disco specifico si può usare il gestore dei dischi su windows (Click destro su risorse del computer -> Gestione -> Gestione Disco))
    - Leggiamo, per intero, il primo settore, quindi i primi 512 bytes
    - Inizializziamo una variabile che chiamiamo StartingPosition su 446 che ci servirà per posizionarci all'interno dell'array in modo corretto
    - Avviamo un ciclo for che va da zero a tre (quindi counter < 4 come check)
    - All'interno del ciclo estraiamo le informazioni presenti nei 16 byte che ci interessano utilizzando come punto di partenza la variabile StartingPosition
    - Incrementiamo la variabile StartingPosition di 16
    - Continuiamo il ciclo
    - Chiudiamo l'accesso al disco

    A questo punto, una volta eseguta la lettura, abbiamo tutte le informazioni che vogliamo sul disco e possiamo quindi visualizzarle come ci pare e piace.

    Però sorge un SERIO problema ... come ci comportiamo con le partizioni "estese"? ovvero le partizioni che contengono altre 4 partizioni a loro volta? ebbene le partizioni "estese" sono normali righe nella tabella con un tipo specifico ... quando si trova quel tipo semplicemente si ci sposta al nuovo settore di inizio indicato nella tabella e si legge sempre un solo settore. Ovviamente bisogna tenere in considerazione, nei calcoli che vengono eseguiti, che può essere attivo o meno l'lba altrimenti i dati letti saranno errati

    [PRATICA]
    Qua c'è del codice che fa questo lavoro. Il codice che parsa la riga della partizione non è completo al 100%, ovvero non legge tutte le informazioni e i tipi di partizione inseriti non sono tutti, devo completare l'elenco ma come esempio, comunque, va più che bene

    file PartitionTable.cs
    codice:
    using System;
    using System.Runtime.InteropServices;
    using System.Collections;
    
    namespace PHPSoft.DiskAnalyzer
    {
    	/// <summary>
    	/// Descrizione di riepilogo per Class1.
    	/// </summary>
    	class PartitionTable
    	{
    		ArrayList partitionEntries;
    
    		public PartitionTable(string Disk)
    		{
    			#region Inizializza le variabili
    			partitionEntries = new ArrayList();
    			#endregion
    
    			#region Apre il disco
    			IntPtr diskHandle = IOWin32Helper.Create(
    				Disk, 
    				FileAccess.GenericRead, 
    				FileShare.Read | FileShare.Write, 
    				CreationDisposition.OpenExisting,
    				FileAttributes.Device | FileAttributes.NoBuffering | FileAttributes.Write_Through);
    
    			if (diskHandle.ToInt32() == -1)
    			{
    				Console.WriteLine("Impossibile accedere al disco");
    				Console.WriteLine("Errore: " + Marshal.GetLastWin32Error().ToString());
    				Console.ReadLine();
    
    				Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
    				return;
    			}
    			#endregion
    
    			#region Acquisisce il primo settore del disco
    			byte[] buffer = new byte[512];
    			int readedBytes = 0;
    			readedBytes = IOWin32Helper.Read(diskHandle, buffer, 0, 512);
    			#endregion
    
    			#region Analizza la tabella delle partizioni nell'MBR
    			int startingPosition = 446;
    			for (int partitionEntryIndex = 0; partitionEntryIndex < 4; partitionEntryIndex++)
    			{
    				partitionEntries.Add(new PartitionEntry(partitionEntryIndex, buffer, startingPosition));
    				startingPosition += 16;
    			}
    			#endregion
    
    			#region Estrae eventuali partizioni estese presenti sul disco
    			// TODO
    			#endregion
    
    			#region Chiude il device
    			IOWin32Helper.Close(diskHandle);
    			#endregion
    		}
    
    		public PartitionEntry[] PartitionEntries
    		{
    			get
    			{
    				return (PartitionEntry[]) partitionEntries.ToArray(typeof(PartitionEntry));
    			}
    		}
    	}
    }
    continua...
    The fastest Redis alternative ... cachegrand! https://github.com/danielealbano/cachegrand

  3. #3
    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
    The fastest Redis alternative ... cachegrand! https://github.com/danielealbano/cachegrand

  4. #4
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,466

    Moderazione

    La aggiungo all'elenco delle pillole.

    In genere, è sempre meglio contattare i moderatori per assicurarsi dell'effettiva pubblicazione di una risorsa (non si può mai sapere) evitando il pericolo di lavorare inutilmente, anche se in generale non ci sono ovviamente problemi.

    Come sempre, lascio aperta la discussione ma esclusivamente per interventi correttivi e revisionistici riguardo la "pillola" stessa, non per chiedere aiuto in merito a qualsiasi problema riguardi l'accesso al disco per cui è possibile aprire una discussione separata tranquillamente, facendo riferimento a questa "pillola" se lo si desidera.

    Ciao e ottimo lavoro!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.