Solved

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

Posted on 2009-05-11
3
2,208 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
3 Comments
 
LVL 11

Author Comment

by:saragani
ID: 24371547
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
ID: 24383159
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
ID: 24461323
Almost 2 weeks and not a single comment. I'm closing this question.
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article will inform Clients about common and important expectations from the freelancers (Experts) who are looking at your Gig.
Today, the web development industry is booming, and many people consider it to be their vocation. The question you may be asking yourself is – how do I become a web developer?
With the power of JIRA, there's an unlimited number of ways you can customize it, use it and benefit from it. With that in mind, there's bound to be things that I wasn't able to cover in this course. With this summary we'll look at some places to go…
Starting up a Project

695 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