Solved

Formating a Floppy or an SD Card in C# using APIs

Posted on 2009-05-11
3
2,124 Views
Last Modified: 2012-05-06
I'm trying to format a drive in C#.

Before anyone of you start suggesting methods like calling the Dos format, or using SHFormatDrive... I'm not interested in those methods.

None of them gives a feedback on the progress. The Dos method opens a Dos Window and the SHFormatDrive opens windows format dialog, which basically sucks!!!


In the past, I've used FormatEx in fmifs.dll which gives me exactly what I want: Feedback on the progress (including percentage), not useless dialog etc..

It was working well in XP (it takes like 2-3 seconds to format an SD Card), but the major problem is that in Windows Vista (YUCK!!!!) it takes more than 1 minute and without any obvious reason.

This is why I'm searching for an alternate method.

I'm attaching the code I've written so far in C#.

Something (probably few things) is/are wrong with it since it doesn't format the drive that I chose... I tried \\.\F:  as the drive.
It gets to the point where it needs to fill outputBuffer with the disk geometry, but I get 0 on the number of cylinders etc, so it doesn't format the drive...

I'm not sure where exactly the problem is.


I hope someone here can help me... Thanks.
using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Windows.Forms;

using System.Runtime.InteropServices;
 
 

namespace Disk_Format

{

    [StructLayout(LayoutKind.Sequential)]

    struct STORAGE_DEVICE_NUMBER

    {

        public int DeviceType;

        public int DeviceNumber;

        public int PartitionNumber;

    }
 

    [StructLayout(LayoutKind.Sequential)]

    struct FORMAT_PARAMETERS

    {

        public MEDIA_TYPE MediaType;

        public uint StartCylinderNumber;

        public uint EndCylinderNumber;

        public uint StartHeadNumber;

        public uint EndHeadNumber;

    }
 

    [StructLayout(LayoutKind.Sequential)]

    public struct DISK_GEOMETRY

    {

        public long Cylinders;

        public MEDIA_TYPE MediaType;

        public int TracksPerCylinder;

        public int SectorsPerTrack;

        public int BytesPerSector;
 

        public long DiskSize

        {

            get

            {

                return Cylinders * (long)TracksPerCylinder * (long)SectorsPerTrack * (long)BytesPerSector;

            }

        }

    }
 

    public enum MEDIA_TYPE

    {

        Unknown,

        F5_1Pt2_512,

        F3_1Pt44_512,

        F3_2Pt88_512,

        F3_20Pt8_512,

        F3_720_512,

        F5_360_512,

        F5_320_512,

        F5_320_1024,

        F5_180_512,

        F5_160_512,

        RemovableMedia,

        FixedMedia,

        F3_120M_512,

        F3_640_512,

        F5_640_512,

        F5_720_512,

        F3_1Pt2_512,

        F3_1Pt23_1024,

        F5_1Pt23_1024,

        F3_128Mb_512,

        F3_230Mb_512,

        F8_256_128,

        F3_200Mb_512,

        F3_240M_512,

        F3_32M_512

    }
 
 

    public partial class Form1 : Form

    {

        const Int64 INVALID_HANDLE_VALUE = -1;

        const uint IOCTL_STORAGE_GET_DEVICE_NUMBER = 0x2D1080;

        public const uint FSCTL_LOCK_VOLUME = 0x00090018;

        public const uint IOCTL_DISK_GET_DRIVE_GEOMETRY = 0x70000;
 

        public const uint IOCTL_DISK_FORMAT_TRACKS = 0x7C018;

        public const uint IOCTL_DISK_FORMAT_TRACKS_EX = 0x7C02C;
 

        public const uint FSCTL_UNLOCK_VOLUME = 0x0009001C;
 
 

        DISK_GEOMETRY outputBuffer = new DISK_GEOMETRY();

                

        #region

        public enum EFileAccess : uint

        {

            /// <summary>

            /// 

            /// </summary>

            GenericRead = 0x80000000,

            /// <summary>

            /// 

            /// </summary>

            GenericWrite = 0x40000000,

            /// <summary>

            /// 

            /// </summary>

            GenericExecute = 0x20000000,

            /// <summary>

            /// 

            /// </summary>

            GenericAll = 0x10000000

        }
 

        [Flags]

        public enum EFileShare : uint

        {

            /// <summary>

            /// 

            /// </summary>

            None = 0x00000000,

            /// <summary>

            /// Enables subsequent open operations on an object to request read access. 

            /// Otherwise, other processes cannot open the object if they request read access. 

            /// If this flag is not specified, but the object has been opened for read access, the function fails.

            /// </summary>

            Read = 0x00000001,

            /// <summary>

            /// Enables subsequent open operations on an object to request write access. 

            /// Otherwise, other processes cannot open the object if they request write access. 

            /// If this flag is not specified, but the object has been opened for write access, the function fails.

            /// </summary>

            Write = 0x00000002,

            /// <summary>

            /// Enables subsequent open operations on an object to request delete access. 

            /// Otherwise, other processes cannot open the object if they request delete access.

            /// If this flag is not specified, but the object has been opened for delete access, the function fails.

            /// </summary>

            Delete = 0x00000004

        }
 

        public enum ECreationDisposition : uint

        {

            /// <summary>

            /// Creates a new file. The function fails if a specified file exists.

            /// </summary>

            New = 1,

            /// <summary>

            /// Creates a new file, always. 

            /// If a file exists, the function overwrites the file, clears the existing attributes, combines the specified file attributes, 

            /// and flags with FILE_ATTRIBUTE_ARCHIVE, but does not set the security descriptor that the SECURITY_ATTRIBUTES structure specifies.

            /// </summary>

            CreateAlways = 2,

            /// <summary>

            /// Opens a file. The function fails if the file does not exist. 

            /// </summary>

            OpenExisting = 3,

            /// <summary>

            /// Opens a file, always. 

            /// If a file does not exist, the function creates a file as if dwCreationDisposition is CREATE_NEW.

            /// </summary>

            OpenAlways = 4,

            /// <summary>

            /// Opens a file and truncates it so that its size is 0 (zero) bytes. The function fails if the file does not exist.

            /// The calling process must open the file with the GENERIC_WRITE access right. 

            /// </summary>

            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

        }

        #endregion
 

        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]

        public static extern IntPtr CreateFile(

           string lpFileName,

           EFileAccess dwDesiredAccess,

           EFileShare dwShareMode,

           IntPtr lpSecurityAttributes,

           ECreationDisposition dwCreationDisposition,

           EFileAttributes dwFlagsAndAttributes,

           IntPtr hTemplateFile);
 

        [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]

        static extern bool DeviceIoControl(IntPtr hDevice, uint dwIoControlCode,

        IntPtr lpInBuffer, uint nInBufferSize,

        IntPtr lpOutBuffer, uint nOutBufferSize,

        out uint lpBytesReturned, IntPtr lpOverlapped);
 

        [DllImport("kernel32.dll", SetLastError=true)]

        static extern bool CloseHandle(IntPtr hHandle);
 
 

        public Form1()

        {

            InitializeComponent();

        }
 
 

        // for example: \\.\C:

        private void button1_Click(object sender, EventArgs e)

        {

            FORMAT_PARAMETERS formatParemeters = new FORMAT_PARAMETERS();
 

            IntPtr h = CreateFile(textBox1.Text.TrimEnd('\\'), EFileAccess.GenericRead | EFileAccess.GenericWrite,EFileShare.Read | EFileShare.Write, IntPtr.Zero, ECreationDisposition.OpenExisting, 0, IntPtr.Zero);

            uint BytesReturned;

            if (h.ToInt32() == INVALID_HANDLE_VALUE)

            {

                System.Diagnostics.Debug.Assert(false);

                return;

            }
 

            bool mybool = DeviceIoControl(h, FSCTL_LOCK_VOLUME, IntPtr.Zero, 0, IntPtr.Zero,0,

              out BytesReturned, IntPtr.Zero);
 
 

            IntPtr outBufferPointer = VarPtr(outputBuffer);

            mybool = DeviceIoControl(h, IOCTL_DISK_GET_DRIVE_GEOMETRY, IntPtr.Zero, 0, outBufferPointer, 24,

              out BytesReturned, IntPtr.Zero);
 
 

            formatParemeters.MediaType = outputBuffer.MediaType;

            formatParemeters.StartCylinderNumber = 0;

            formatParemeters.StartHeadNumber = 0;

            formatParemeters.EndCylinderNumber = (uint)(outputBuffer.Cylinders & 0xFFFFFFFF - 1);

            formatParemeters.EndHeadNumber = (uint)(outputBuffer.TracksPerCylinder - 1);
 

            uint dwBufSize;

            dwBufSize = (uint)(outputBuffer.TracksPerCylinder * 16);

            ushort[] bad_track = new ushort[outputBuffer.TracksPerCylinder];
 

            for (int i = 0; i < bad_track.Length; i++)

            {

                bad_track[i] = 0;

            }
 

            IntPtr formatParametersPointer = VarPtr(formatParemeters);

            IntPtr bad_trackPointer = VarPtr(bad_track);
 

            mybool = DeviceIoControl(h, IOCTL_DISK_FORMAT_TRACKS, formatParametersPointer, 20, bad_trackPointer, dwBufSize,

              out BytesReturned, IntPtr.Zero);
 
 

            mybool = DeviceIoControl(h, FSCTL_UNLOCK_VOLUME, IntPtr.Zero, 0, IntPtr.Zero, 0,

              out BytesReturned, IntPtr.Zero);
 

        }
 

        static IntPtr VarPtr(object obj)

        {

            GCHandle GC = GCHandle.Alloc(obj, GCHandleType.Pinned);

            IntPtr ret = GC.AddrOfPinnedObject();

            return ret;

        }

    }

}

Open in new window

0
Comment
Question by:saragani
  • 3
3 Comments
 
LVL 11

Author Comment

by:saragani
Comment Utility
OK, lets start with a VB6 example, OK?

I've written an example with VB6 and it doesn't work. I've later searched the Internet for an example in VB6 and found one... and yes, It doesn't work either.

During the searches I've read somewhere that IOCTL_DISK_FORMAT_TRACKS only works with Floppy Disks... (I've read that it doesn't work on Hard Drives is I remember correctly).

So how exactly companies like Panasonic have managed to create a tool for formating an SD/USB Flash drive??
(And their tool is very good)


If you are having problems writing an example in C#, then VB6 could be a good start. (Maybe instead of using IOCTL_DISK_FORMAT_TRACKS we need to write the FAT32 by ourselves??)

Isn't there an expert here that can help me with that task?

Thanks
0
 
LVL 11

Author Comment

by:saragani
Comment Utility
Maybe using the UFAT.dll can help??
(I know it has format capabilities... I understand that FMIFS.dll uses it)

Anyone has an idea on how to use it in order to format a USB drive?
0
 
LVL 11

Accepted Solution

by:
saragani earned 0 total points
Comment Utility
Almost 2 weeks and not a single comment. I'm closing this question.
0

Featured Post

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Help with my python script 6 144
copyEndy  challenge 15 55
changeXy challenge 13 56
VB 6.0 printer how to align 6 49
This is about my first experience with programming Arduino.
In this post we will learn how to connect and configure Android Device (Smartphone etc.) with Android Studio. After that we will run a simple Hello World Program.
In this fourth video of the Xpdf series, we discuss and demonstrate the PDFinfo utility, which retrieves the contents of a PDF's Info Dictionary, as well as some other information, including the page count. We show how to isolate the page count in a…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now