Solved

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

Posted on 2009-05-11
3
2,153 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
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

Netscaler Common Configuration How To guides

If you use NetScaler you will want to see these guides. The NetScaler How To Guides show administrators how to get NetScaler up and configured by providing instructions for common scenarios and some not so common ones.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
groupSumClump challenge 9 115
wordlen challenge 3 67
Looking for a network enabled locker remotely controlled like Amazon locker 2 76
Help Required 3 97
Here we come across an interesting topic of coding guidelines while designing automation test scripts. The scope of this article will not be limited to QTP but to an overall extent of using VB Scripting for automation projects. Introduction Now…
Although it can be difficult to imagine, someday your child will have a career of his or her own. He or she will likely start a family, buy a home and start having their own children. So, while being a kid is still extremely important, it’s also …
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …
In this fifth video of the Xpdf series, we discuss and demonstrate the PDFdetach utility, which is able to list and, more importantly, extract attachments that are embedded in PDF files. It does this via a command line interface, making it suitable …

777 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