*** 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...