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

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
        public int DeviceType;
        public int DeviceNumber;
        public int PartitionNumber;
        public MEDIA_TYPE MediaType;
        public uint StartCylinderNumber;
        public uint EndCylinderNumber;
        public uint StartHeadNumber;
        public uint EndHeadNumber;
    public struct DISK_GEOMETRY
        public long Cylinders;
        public MEDIA_TYPE MediaType;
        public int TracksPerCylinder;
        public int SectorsPerTrack;
        public int BytesPerSector;
        public long DiskSize
                return Cylinders * (long)TracksPerCylinder * (long)SectorsPerTrack * (long)BytesPerSector;
    public enum MEDIA_TYPE
    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();
        public enum EFileAccess : uint
            /// <summary>
            /// </summary>
            GenericRead = 0x80000000,
            /// <summary>
            /// </summary>
            GenericWrite = 0x40000000,
            /// <summary>
            /// </summary>
            GenericExecute = 0x20000000,
            /// <summary>
            /// </summary>
            GenericAll = 0x10000000
        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
        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
        [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()
        // 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)
            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

LVL 11
Who is Participating?
saraganiConnect With a Mentor Author Commented:
Almost 2 weeks and not a single comment. I'm closing this question.
saraganiAuthor Commented:
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?

saraganiAuthor Commented:
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?
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.