/// <summary>Discover partitions</summary> internal unsafe void Discover() { VolumePartition fakePartition = new VolumePartition(_rawHandle, 0, 16); using (IPartitionClusterData rawData = fakePartition.ReadSectors(0)) { uint minSector = uint.MaxValue; uint maxSector = 0; byte *masterBootRecord = rawData.Data; if (0x55 != masterBootRecord[510]) { throw new ApplicationException(); } if (0xAA != masterBootRecord[511]) { throw new ApplicationException(); } // From http://thestarman.pcministry.com/asm/mbr/PartTables.htm // TODO : This is suitable for a Master Boot Record. Other types of boot records exist such // as the ExtendedBoot Record format. for (uint partitionIndex = 0; partitionIndex < 4; partitionIndex++) { IntPtr partitionHandle; if (!Natives.DuplicateHandle(new IntPtr(-1), _rawHandle, new IntPtr(-1), out partitionHandle, 0 /* ignored because same access */, false, 2 /*DUPLICATE_SAME_ACCESS*/)) { throw new ApplicationException(); } GenericPartition newPartition = GenericPartition.Create(partitionHandle, masterBootRecord, 446 + (16 * partitionIndex)); if (null == newPartition) { Natives.CloseHandle(partitionHandle); } else { // TODO : This algorithm doesn't let us witness the extra sectors after the last partition. if (minSector > newPartition.StartSector) { minSector = newPartition.StartSector; } if (maxSector < (newPartition.StartSector + newPartition.SectorCount - 1)) { maxSector = newPartition.StartSector + newPartition.SectorCount - 1; } _partitions.Add(newPartition); } } Console.WriteLine("Found {0} partitions.", _partitions.Count); if (maxSector < minSector) { throw new ApplicationException(); } _volumePartition = new VolumePartition(_rawHandle, minSector, maxSector - minSector); return; } }
public static unsafe int Main(string[] args) { InstallExceptionHandlers(); using (PartitionDataDisposableBatch mainBatch = PartitionDataDisposableBatch.CreateNew()) { DisplayVersion(); IntPtr handle = IntPtr.Zero; int nativeError; DiskGeometry geometry = new DiskGeometry(); try { handle = Natives.CreateFile2(@"\\.\PhysicalDrive0", 0x80000000 /* GENERIC_READ */, 0x02 /* FILE_SHARE_WRITE */, 3 /* OPEN_EXISTING */, IntPtr.Zero); nativeError = Marshal.GetLastWin32Error(); if ((IntPtr.Zero == handle) || (0 != nativeError)) { Console.WriteLine("Physical drive opening failed. Error 0x{0:X8}", nativeError); return(1); } geometry.Acquire(handle); _partitionManager = new PartitionManager(handle, geometry); _partitionManager.Discover(); InterpretActivePartitions(); if (FeaturesContext.InvariantChecksEnabled) { NtfsMFTFileRecord.AssertMFTRecordCachingInvariance(_partitionManager); } // TODO : Configure TrackedPartitionIndex from command line arguments. foreach (GenericPartition partition in _partitionManager.EnumeratePartitions()) { if (!partition.ShouldCapture) { continue; } NtfsPartition ntfsPartition = partition as NtfsPartition; NtfsPartition.Current = ntfsPartition; // Basic functionnality tests. Don't remove. //ntfsPartition.CountFiles(); //ntfsPartition.MonitorBadClusters(); //ntfsPartition.ReadBitmap(); // Dump bad clusters. ntfsPartition.DumpBadClusters(); // Dump UsnJournal PrototypeUsnJournal(); new NtfsUsnJournalReader(ntfsPartition).Run(); // Dump LogFile // new NtfsLogFileReader(ntfsPartition).Run(); // Locate file. // string fileName = @"TEMP\AsciiTes.txt"; string fileName = @"$Extend\$UsnJrnl"; NtfsIndexEntryHeader *fileDescriptor = ntfsPartition.FindFile(fileName); if (null == fileDescriptor) { throw new System.IO.FileNotFoundException(fileName); } IPartitionClusterData fileData = null; NtfsFileRecord * usnJournalFileRecord = ntfsPartition.GetFileRecord(fileDescriptor->FileReference, ref fileData); if ((null == usnJournalFileRecord) || (null == fileData)) { throw new ApplicationException(); } try { usnJournalFileRecord->EnumerateRecordAttributes( delegate(NtfsAttribute * attribute, Stream dataStream) { attribute->Dump(); return(true); }); // For debugging purpose. // fileRecord->BinaryDumpContent(); // TODO : Do something with the file. } finally { if (null != fileData) { fileData.Dispose(); } } } return(0); } finally { if (IntPtr.Zero == handle) { Natives.CloseHandle(handle); handle = IntPtr.Zero; } } } }