public override bool GetPartitionDetails() { uint BytesRead; ulong FATSize; IntPtr BootSectorPtr = Marshal.AllocHGlobal(512); NativeOverlapped Overlapped = new NativeOverlapped(); var result = PInvoke.ReadFile(Volume.Handle, BootSectorPtr, 512, out BytesRead, ref Overlapped); if (!result) { Debug.WriteLine("Error #{0} occurred trying to read volume {1}", Marshal.GetLastWin32Error(), Volume.RootPath); return(false); } var BootSector = new PInvoke.FATBootSector(BootSectorPtr); if (BootSector.Signature != 0xAA55 || (((BootSector.BS_jmpBoot[0] != 0xEB) || (BootSector.BS_jmpBoot[2] != 0x90)) && (BootSector.BS_jmpBoot[0] != 0xE9))) { Debug.WriteLine("Volume is not a valid FAT partition"); return(false); } // Fetch values from the bootblock and determine what FAT this is, FAT12, FAT16, or FAT32. BytesPerSector = BootSector.BytesPerSector; if (BytesPerSector == 0) { Debug.WriteLine("This is not a FAT disk (BytesPerSector is zero)."); return(false); } SectorsPerCluster = BootSector.SectorsPerCluster; if (SectorsPerCluster == 0) { Debug.WriteLine("This is not a FAT disk (SectorsPerCluster is zero)."); return(false); } TotalSectors = BootSector.TotalSectors16; if (TotalSectors == 0) { TotalSectors = BootSector.TotalSectors32; } RootDirSectors = (ulong)((BootSector.RootEntries * 32) + (BootSector.BytesPerSector - 1)) / BootSector.BytesPerSector; uint SectorsPerFAT = BootSector.SectorsPerFAT; if (SectorsPerFAT == 0) { SectorsPerFAT = BootSector.FAT1632Info.FAT32_SectorsPerFAT32; } FirstDataSector = BootSector.ReservedSectors + (BootSector.NumberOfFATs * SectorsPerFAT) + RootDirSectors; DataSector = TotalSectors - (BootSector.ReservedSectors + (BootSector.NumberOfFATs * SectorsPerFAT) + RootDirSectors); ClusterCount = DataSector / BootSector.SectorsPerCluster; if (ClusterCount < 4085) { Type = FATTypes.FAT12; Debug.WriteLine("This is a FAT12 disk."); } else if (ClusterCount < 65525) { Type = FATTypes.FAT16; Debug.WriteLine("This is a FAT16 disk."); } else { Type = FATTypes.FAT32; Debug.WriteLine("This is a FAT32 disk."); } BytesPerCluster = BytesPerSector * SectorsPerCluster; TotalClusters = (uint)ClusterCount; Debug.WriteLine(" OEMName: {0}", BootSector.BS_OEMName); Debug.WriteLine(" BytesPerSector: {0:d}", BytesPerSector); Debug.WriteLine(" TotalSectors: {0:d}", TotalSectors); Debug.WriteLine(" SectorsPerCluster: {0:d}", SectorsPerCluster); Debug.WriteLine(" RootDirSectors: {0:d}", RootDirSectors); Debug.WriteLine(" FATSz: {0:d}", SectorsPerFAT); Debug.WriteLine(" FirstDataSector: {0:d}", FirstDataSector); Debug.WriteLine(" DataSec: {0:d}", DataSector); Debug.WriteLine(" CountofClusters: {0:d}", ClusterCount); Debug.WriteLine(" ReservedSectors: {0:d}", BootSector.ReservedSectors); Debug.WriteLine(" NumberFATs: {0:d}", BootSector.NumberOfFATs); Debug.WriteLine(" RootEntriesCount: {0:d}", BootSector.RootEntries); Debug.WriteLine(" MediaType: {0:X}", BootSector.MediaDescriptor); Debug.WriteLine(" SectorsPerTrack: {0:d}", BootSector.SectorsPerTrack); Debug.WriteLine(" NumberOfHeads: {0:d}", BootSector.Heads); Debug.WriteLine(" HiddenSectors: {0:d}", BootSector.HiddenSectors); if (Type != FATTypes.FAT32) { Debug.WriteLine(" BS_DrvNum: {0:d}", BootSector.FAT1632Info.FAT16_LogicalDriveNumber); Debug.WriteLine(" BS_BootSig: {0:d}", BootSector.FAT1632Info.FAT16_ExtendedSignature); Debug.WriteLine(" BS_VolID: {0:d}", BootSector.FAT1632Info.FAT16_PartitionSerialNumber); Debug.WriteLine(" VolLab: {0}", BootSector.FAT1632Info.FAT16_VolumeName); Debug.WriteLine(" FilSysType: {0}", BootSector.FAT1632Info.FAT16_FSType); } else { Debug.WriteLine(" FATSz32: {0:d}", BootSector.FAT1632Info.FAT32_SectorsPerFAT32); Debug.WriteLine(" ExtFlags: {0:d}", BootSector.FAT1632Info.FAT32_ExtFlags); Debug.WriteLine(" FSVer: {0:d}", BootSector.FAT1632Info.FAT32_FSVer); Debug.WriteLine(" RootClus: {0:d}", BootSector.FAT1632Info.FAT32_RootDirStart); Debug.WriteLine(" FSInfo: {0:d}", BootSector.FAT1632Info.FAT32_FSInfoSector); Debug.WriteLine(" BkBootSec: {0:d}", BootSector.FAT1632Info.FAT32_BackupBootSector); Debug.WriteLine(" DrvNum: {0:d}", BootSector.FAT1632Info.FAT32_LogicalDriveNumber); Debug.WriteLine(" BootSig: {0:d}", BootSector.FAT1632Info.FAT32_ExtendedSignature); Debug.WriteLine(" VolID: {0:d}", BootSector.FAT1632Info.FAT32_PartitionSerialNumber); Debug.WriteLine(" VolLab: {0}", BootSector.FAT1632Info.FAT32_VolumeName); Debug.WriteLine(" FilSysType: {0}", BootSector.FAT1632Info.FAT32_FSType); } switch (Type) { case FATTypes.FAT12: { FATSize = ClusterCount + 1; break; } case FATTypes.FAT16: { FATSize = (ClusterCount + 1) * 2; break; } case FATTypes.FAT32: { FATSize = (ClusterCount + 1) * 4; break; } default: { FATSize = 0; break; } } if (FATSize % BytesPerSector > 0) { FATSize = FATSize + BytesPerSector - FATSize % BytesPerSector; } PInvoke.LARGE_INTEGER Trans = new PInvoke.LARGE_INTEGER { QuadPart = BootSector.ReservedSectors * BytesPerSector }; IntPtr FATDataPtr = Marshal.AllocHGlobal((int)FATSize); NativeOverlapped nativeOverlapped = new NativeOverlapped { EventHandle = IntPtr.Zero, OffsetLow = (int)Trans.LowPart, OffsetHigh = Trans.HighPart }; PInvoke.ReadFile(Volume.Handle, FATDataPtr, (uint)FATSize, out BytesRead, ref nativeOverlapped); PInvoke.FATData FatData = new PInvoke.FATData(FATDataPtr, Type, FATSize); return(true); }
private bool GetClusterInfo(FileInfo Info, ref SafeFileHandle Handle) { Info.Fragments.Clear(); string FullName = GetDBDir(Info.DirIndice) + Info.Name; PInvoke.BY_HANDLE_FILE_INFORMATION FileInfo; if ((Handle == null) || Handle.IsClosed || Handle.IsInvalid) { Handle = PInvoke.CreateFile( FullName, PInvoke.GENERIC_READ, PInvoke.FILE_SHARE_READ | PInvoke.FILE_SHARE_WRITE, IntPtr.Zero, PInvoke.OPEN_EXISTING, (Info.Attributes.Directory) ? PInvoke.FILE_FLAG_BACKUP_SEMANTICS : 0, IntPtr.Zero ); } if (Handle.IsInvalid || Handle.IsClosed) { Debug.WriteLine("Error #{0} occurred trying to open file '{1}'", Marshal.GetLastWin32Error(), FullName); Info.Attributes.AccessDenied = true; return(false); } var Result = PInvoke.GetFileInformationByHandle(Handle, out FileInfo); if (!Result) { Info.Attributes.AccessDenied = true; Debug.WriteLine("GetFileInformationByHandle ('{0}') failed\n", FullName); Handle.Close(); return(false); } // Get cluster allocation information PInvoke.LARGE_INTEGER StartingVCN = new PInvoke.LARGE_INTEGER(); IntPtr pDest = IntPtr.Zero; uint BytesReturned = 0; // Grab info one extent at a time, until it's done grabbing all the extent data // Yeah, well it doesn't give us a way to ask L"how many extents?" that I know of ... // btw, the Extents variable tends to only reflect memory usage, so when we have // all the extents we look at the structure Win32 gives us for the REAL count! uint Extents = 10; const uint RETRIEVAL_POINTERS_BUFFER_SIZE = 28; StartingVCN.QuadPart = 0; GCHandle handle = GCHandle.Alloc(StartingVCN, GCHandleType.Pinned); IntPtr StartingVCNPtr = handle.AddrOfPinnedObject(); do { Extents *= 2; var RetSize = RETRIEVAL_POINTERS_BUFFER_SIZE + (uint)((Extents - 1) * Marshal.SizeOf(typeof(PInvoke.LARGE_INTEGER)) * 2); pDest = pDest != IntPtr.Zero ? Marshal.ReAllocHGlobal(pDest, (IntPtr)RetSize) : Marshal.AllocHGlobal((int)RetSize); Result = PInvoke.DeviceIoControl ( Handle, PInvoke.FSConstants.FSCTL_GET_RETRIEVAL_POINTERS, StartingVCNPtr, (uint)Marshal.SizeOf(typeof(PInvoke.LARGE_INTEGER)), pDest, RetSize, ref BytesReturned, IntPtr.Zero ); if (!Result) { if (Marshal.GetLastWin32Error() != PInvoke.ERROR_MORE_DATA) { Debug.WriteLine("Error #{0} occurred trying to get retrieval pointers for file '{1}", Marshal.GetLastWin32Error(), FullName); Info.Clusters = 0; Info.Attributes.AccessDenied = true; Info.Attributes.Process = false; Info.Fragments.Clear(); Handle.Close(); Marshal.FreeHGlobal(pDest); return(false); } Extents++; } } while (!Result); var Retrieval = new PInvoke.RETRIEVAL_POINTERS_BUFFER(pDest); // Readjust extents, as it only reflects how much memory was allocated and may not // be accurate Extents = (uint)Retrieval.ExtentCount; // Ok, we have the info. Now translate it. hrmrmr Info.Fragments.Clear(); for (int i = 0; i < Extents; i++) { Extent Add; Add.StartLCN = Retrieval.Extents[i].Lcn.QuadPart; if (i != 0) { Add.Length = Retrieval.Extents[i].NextVcn.QuadPart - Retrieval.Extents[i - 1].NextVcn.QuadPart; } else { Add.Length = Retrieval.Extents[i].NextVcn.QuadPart - Retrieval.StartingVcn.QuadPart; } Info.Fragments.Add(Add); } Marshal.FreeHGlobal(pDest); return(true); }