Hola

ho un problemuccio un po particolare: ho necessità di accedere al disco direttamente senza passare da windows per poi poter leggere prima la tabella delle partizioni e poi il contenuto delle partizioni

La prima cosa che ho pensato è stata: apro il disco usando le path UNC tanto File.Open usa sicuramente CreateFile

Teoricamente corretto ma peccato che non funzioni, infatti butta fuori una bella eccezione dicendo:
FileStream non aprirà periferiche Win32 quali partizioni su disco e unità a nastro. Non utilizzare "\\.\" nel percorso.
Di conseguenza ho pensato: vabbé richiamo io direttamente CreateFile e mi risolvo il problema

Scrivo il codice, faccio qualche correzione, e va senza troppi intoppi ... adesso apro e chiudo il device senza problemi ora però sorge un problema: come ci scrivo? Ho pensato in primis di usare FileStream dato che accetta dei puntatori a file e siccome quello che mi restituisce CreateFile è proprio un puntatore ho scritto il codice

Risultato: quando inizializzo la classe FileStream mi sputa fuori una bella eccezione
Funzione non corretta.

at System.IO.__Error.WinIOError(Int32 errorCode, String str)
at System.IO.FileStream.get_Length()
at System.IO.FileStream..ctor(IntPtr handle, FileAccess access, Boolean ownsH
andle, Int32 bufferSize, Boolean isAsync)
at NTFSReader.Class1.Main(String[] args) in c:\documents and settings\daniele
_dll\documenti\visual studio projects\ntfsreader\class1.cs:line 128
ed è abbastanza evidente che il problema lo ha perché filestream, pensando che il file è un normalissimo handle di file, prova a leggere la lunghezza totale del file ottenendo però un'errore :\

Qualcuno di voi ha idea di come aggirare il problema? devo per forza scrivermi una classettina che mi esponga tutte le varie api di windows per la gestione dei file? Vorrei evitare perché fare questo vuol dire perdere un botto a livello di prestazioni!

per completezza posto il codice:
codice:
namespace DiskReader
{
	class Class1
	{
		[DllImport("kernel32.dll", SetLastError=true)]
		public static extern IntPtr CreateFile(
			string lpFileName,
			EFileAccess dwDesiredAccess,
			EFileShare dwShareMode,
			IntPtr lpSecurityAttributes,
			ECreationDisposition dwCreationDisposition,
			EFileAttributes dwFlagsAndAttributes,
			IntPtr hTemplateFile);

		[DllImport("kernel32.dll", SetLastError=true)]
		[return: MarshalAs(UnmanagedType.Bool)]
		static extern bool CloseHandle(IntPtr hObject);

		[Flags]
		public enum EFileAccess : uint
		{
			GenericRead = 0x80000000,
			GenericWrite = 0x40000000,
			GenericExecute = 0x20000000,
			GenericAll = 0x10000000,
		}

		[Flags]
		public enum EFileShare : uint
		{
			None = 0x00000000,
			Read = 0x00000001,
			Write = 0x00000002,
			Delete = 0x00000004,
		}

		public enum ECreationDisposition : uint
		{
			New = 1,
			CreateAlways = 2,
			OpenExisting = 3,
			OpenAlways = 4,
			TruncateExisting = 5,
		}

		[Flags]
		public enum EFileAttributes : 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
		}

		/// <summary>
		/// Il punto di ingresso principale dell'applicazione.
		/// </summary>
		[STAThread]
		static void Main(string[] args)
		{

			// Apre il disco
			IntPtr diskHandle = CreateFile(
				@"\\.\PhysicalDrive0", 
				EFileAccess.GenericRead | EFileAccess.GenericWrite, 
				EFileShare.Read | EFileShare.Write, 
				IntPtr.Zero, 
				ECreationDisposition.OpenExisting, 
				EFileAttributes.Device | EFileAttributes.NoBuffering | EFileAttributes.Write_Through, 
				IntPtr.Zero);

			if (diskHandle.ToInt32() == -1)
			{
				Console.WriteLine("Errore: " + Marshal.GetLastWin32Error().ToString());
				Console.ReadLine();

				Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());

				return;
			}

			// Inizializza lo stream
			FileStream fileStream = null;
			try
			{
				fileStream = new FileStream(diskHandle, FileAccess.Read, true, 8096, false);
			}
			catch(IOException e)
			{
				Console.WriteLine(e.Message);
				Console.WriteLine();
				Console.WriteLine(e.StackTrace);
				Console.WriteLine();
				Console.WriteLine(e.Source.ToString());

				Console.ReadLine();
				return;
			}

			// Si posizione alla prima partizione
			fileStream.Seek(446, SeekOrigin.Begin);

			// Legge le varie entries della tabella
			for (int i = 0; i < 4; i++)
			{
				Console.WriteLine("Partition 1:");

				byte[] buffer = new byte[16];
				fileStream.Read(buffer, 0, buffer.Length);

				// Verifica se la partizione è avviabile
				if (buffer[0] == 0)
				{
					Console.WriteLine("\tAvviabile: SI");
				}
				else
				{
					Console.WriteLine("\tAvviabile: NO");
				}

				Console.WriteLine("");
			}

			// Chiude lo stream
			fileStream.Close();
			CloseHandle(diskHandle);

			Console.ReadLine();
		}
	}
}