示例#1
0
        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);
        }
示例#2
0
        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);
        }