Example #1
0
        private static void ExampleBitmap()
        {
            const string drive = @"\\.\C:";

            Console.WriteLine(@"## Exmaple on {0} ##", drive);
            SafeFileHandle volumeHandle = CreateFile(drive, FileAccess.ReadWrite, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, FileAttributes.Normal, IntPtr.Zero);

            if (volumeHandle.IsInvalid)
            {
                int lastError = Marshal.GetLastWin32Error();

                Console.WriteLine(@"!! Invalid {0}; Error ({1}): {2}", drive, lastError, new Win32Exception(lastError).Message);
                Console.WriteLine();
                return;
            }

            using (FilesystemDeviceWrapper fsIo = new FilesystemDeviceWrapper(volumeHandle, true))
            {
                // Bitmap
                VOLUME_BITMAP_BUFFER bitmap = fsIo.FileSystemGetVolumeBitmap();

                Console.WriteLine("Bitmap: {0:N0} clusters", bitmap.Buffer.Length);

                int width  = 10000;
                int height = (int)Math.Ceiling(bitmap.BitmapSize / (double)width);

                Console.WriteLine("W/H: {0:N0} / {1:N0}", width, height);

                using (Bitmap bmp = new Bitmap(width, height))
                {
                    using (Graphics g = Graphics.FromImage(bmp))
                        g.Clear(Color.Green);

                    for (int i = 0; i < bitmap.Buffer.Length; i++)
                    {
                        int x = i % width;
                        int y = i / width;

                        if (bitmap.Buffer[i])
                        {
                            bmp.SetPixel(x, y, Color.Black);
                        }
                        else
                        {
                            bmp.SetPixel(x, y, Color.White);
                        }

                        if (y % 100 == 0 && x == 0)
                        {
                            Console.WriteLine("{0:N0} / {1:N0}", y, height);
                        }
                    }

                    bmp.Save("test.png", ImageFormat.Png);
                }
            }

            Console.WriteLine();
        }
        /// <summary><see cref="http://msdn.microsoft.com/en-us/library/windows/desktop/aa364573(v=vs.85).aspx"/></summary>
        public VOLUME_BITMAP_BUFFER FileSystemGetVolumeBitmap(ulong startingLcn = 0)
        {
            STARTING_LCN_INPUT_BUFFER startingLcnStruct = new STARTING_LCN_INPUT_BUFFER();

            startingLcnStruct.StartingLcn = startingLcn;

            // Fetch 128 bytes (this includes the size parameter of the VOLUME_BITMAP_BUFFER structure.
            int lastError;

            byte[] data = DeviceIoControlHelper.InvokeIoControl(Handle, IOControlCode.FsctlGetVolumeBitmap, 128, startingLcnStruct, out lastError);

            // Is there more data? (Most often there is).
            if (lastError == 234)
            {
                // Parse length attribute (2'nd 64-bit attribute)
                uint newLength = (uint)BitConverter.ToUInt64(data, 8);

                // Length: Clusters / 8 + 2x 64 bit numbers
                newLength = (uint)Math.Ceiling(newLength / 8d) + 2 * 8;

                data = DeviceIoControlHelper.InvokeIoControl(Handle, IOControlCode.FsctlGetVolumeBitmap, newLength, startingLcnStruct, out lastError);
            }

            // Ensure the last call to InvokeIoControl succeeded.
            if (lastError != 0)
            {
                throw new Win32Exception(lastError, "Couldn't invoke FileSystemGetVolumeBitmap. LastError: " + Utils.GetWin32ErrorMessage(lastError));
            }

            // Build the VOLUME_BITMAP_BUFFER structure.
            VOLUME_BITMAP_BUFFER res = new VOLUME_BITMAP_BUFFER();

            res.StartingLcn = BitConverter.ToUInt64(data, 0);
            res.BitmapSize  = BitConverter.ToUInt64(data, sizeof(UInt64));

            res.Buffer = new BitArray((int)res.BitmapSize);

            for (int i = 0; i < res.Buffer.Length; i++)
            {
                int  dataByteIndex = sizeof(UInt64) * 2 + i / 8;
                byte dataByte      = data[dataByteIndex];

                int byteIdx = i % 8;

                res.Buffer[i] = ((dataByte >> byteIdx) & 1) == 1;
            }

            return(res);
        }
Example #3
0
        private static void ExampleDefragmentDir()
        {
            const string dir   = @"C:\Windows";
            string       drive = @"\\.\" + Directory.GetDirectoryRoot(dir).Substring(0, 2);

            Console.WriteLine(@"## Exmaple on {0} on drive {1} ##", dir, drive);

            // Open volume to defragment on
            SafeFileHandle driveHandle = CreateFile(drive, FileAccess.ReadWrite, FileShare.ReadWrite, IntPtr.Zero,
                                                    FileMode.Open, FileAttributes.Normal, IntPtr.Zero);

            if (driveHandle.IsInvalid)
            {
                int lastError = Marshal.GetLastWin32Error();

                Console.WriteLine(@"!! Invalid {0}; Error ({1}): {2}", drive, lastError, new Win32Exception(lastError).Message);
                Console.WriteLine();
                return;
            }

            using (FilesystemDeviceWrapper fsIo = new FilesystemDeviceWrapper(driveHandle, true))
            {
                // Get the drive bitmap
                VOLUME_BITMAP_BUFFER bitmap = fsIo.FileSystemGetVolumeBitmap();

                Console.WriteLine("Got the drive bitmap, it contains {0:N0} clusters and starts at LCN: {1:N0}", bitmap.BitmapSize, bitmap.StartingLcn);

                string[] files = Directory.GetFiles(dir, "*", SearchOption.TopDirectoryOnly);
                Console.WriteLine("Beginning work on {0} files", files.Length);

                foreach (string file in files)
                {
                    Console.WriteLine("Beginning work on {0}", file);

                    // Open file to defragment
                    SafeFileHandle fileHandle = CreateFile(file, FileAccess.Read, FileShare.ReadWrite, IntPtr.Zero,
                                                           FileMode.Open, FileAttributes.Normal, IntPtr.Zero);

                    if (fileHandle.IsInvalid)
                    {
                        int lastError = Marshal.GetLastWin32Error();

                        Console.WriteLine(@"!! Invalid {0}; Error ({1}): {2}", file, lastError, new Win32Exception(lastError).Message);
                        continue;
                    }

                    using (FilesystemDeviceWrapper fileIo = new FilesystemDeviceWrapper(fileHandle, true))
                    {
                        // Find all fragments of the file
                        FileExtentInfo[] extents;
                        try
                        {
                            extents = fileIo.FileSystemGetRetrievalPointers();
                        }
                        catch (Win32Exception ex)
                        {
                            Console.WriteLine("Couldn't get file extents: " + ex.Message);
                            continue;
                        }

                        if (extents.Length == 1)
                        {
                            Console.WriteLine("File is already defragmented");
                            continue;
                        }
                        Console.WriteLine("File has {0} fragments", extents.Length);

                        // Calculate number of clusters we need to find
                        int clustersNeeded = (int)extents.Sum(s => (decimal)s.Size);

                        Console.WriteLine("We need to find {0:N0} free clusters, for this file.", clustersNeeded);

                        // Find a sequential area of [clustersNeeded] free clusters
                        ulong foundFreeLCN = 0;                                                      // The result of the search
                        uint  maxStart     = (uint)(bitmap.Buffer.Length - (decimal)clustersNeeded); // There's no point searching beyond this LCN

                        // Enumerate clusters
                        for (uint i = 0; i < maxStart; i++)
                        {
                            // Check bitmap, find location with [clustersNeeded] free clusters
                            bool found = true;
                            for (uint x = i; x < i + clustersNeeded; x++)
                            {
                                if (bitmap.Buffer[(int)x])
                                {
                                    // Found an occupied cluster
                                    found = false;

                                    // Advance the pointer, so that we don't have to re-search the same clusters again.
                                    i = x;

                                    break;
                                }
                            }

                            if (found)
                            {
                                // We found a free block!
                                foundFreeLCN = i + bitmap.StartingLcn;
                                break;
                            }
                        }

                        // Did we find a free area?
                        if (foundFreeLCN > 0)
                        {
                            Console.WriteLine("Found {0:N0} free clusters starting at LCN: {1:N0}", clustersNeeded, foundFreeLCN);

                            try
                            {
                                fsIo.FileSystemMoveFile(fileHandle.DangerousGetHandle(), 0, foundFreeLCN, (uint)clustersNeeded);

                                // Mark newly used areas as used
                                ulong upperFreeLCN = foundFreeLCN + (ulong)clustersNeeded;
                                for (ulong i = foundFreeLCN; i < upperFreeLCN; i++)
                                {
                                    bitmap.Buffer[(int)i] = true;
                                }

                                // Mark newly freed areas as free
                                foreach (FileExtentInfo extent in extents)
                                {
                                    for (ulong i = extent.Lcn; i < extent.Lcn + extent.Size; i++)
                                    {
                                        bitmap.Buffer[(int)i] = false;
                                    }
                                }
                            }
                            catch (Win32Exception ex)
                            {
                                Console.WriteLine("Unable to move file: " + ex.Message);
                            }
                        }
                        else
                        {
                            Console.WriteLine("Unable to find {0:N0} contigous free clusters", clustersNeeded);
                        }

                        extents = fileIo.FileSystemGetRetrievalPointers();
                        Console.WriteLine("File now has {0} fragment(s)", extents.Length);
                    }
                }
            }

            Console.WriteLine("Done... ");
            Console.ReadLine();
            Console.WriteLine();
        }