This code demonstrates how to read & write raw data from a floppy disk (or
other removable disk). The CreateFile API call can also be used to open
other Win32 devices such as COM ports.
This code requires the following imports:
Imports
System.Management
Imports System.IO
The first thing we do is to declare the API calls we'll be using.
#
Region
"API"
Private
Declare
Function CreateFile
Lib
"kernel32"
Alias
"CreateFileA" (ByVal
lpFileName As
String, _
ByVal dwDesiredAccess
As Int32, _
ByVal dwShareMode As
Int32, _
ByVal lpSecurityAttributes
As IntPtr, _
ByVal dwCreationDistribution
As Int32, _
ByVal dwFlagsAndAttributes
As Int32, _
ByVal hTemplateFile
As Int32) As
IntPtr
Private
Declare
Function ReadFile
Lib
"kernel32" (ByVal
hFile As IntPtr, _
ByVal lpBuffer As
Byte(), _
ByVal nNumberOfBytesToRead
As Int32, _
ByRef lpNumberOfBytesRead
As Int32, _
ByVal lpOverlapped
As IntPtr) As
Int32
Private
Declare
Function WriteFile
Lib
"kernel32" (ByVal
hFile As IntPtr, _
ByVal lpBuffer As
Byte(), _
ByVal nNumberOfBytesToWrite
As Int32, _
ByRef lpNumberOfBytesWritten
As Int32, _
ByVal lpOverlapped
As IntPtr) As
Int32
Private
Declare
Function CloseHandle
Lib
"kernel32" (ByVal
hObject As IntPtr)
As
Long
Const GENERIC_READ
As Int32 = &H80000000
Const
GENERIC_WRITE As
Int32 = &H40000000
Const
OPEN_EXISTING As
Int32 = 3
Const
FILE_SHARE_READ As
Int32 = &H1
Const
FILE_SHARE_WRITE As
Int32 = &H2
Const
FILE_ATTRIBUTE_NORMAL As
Int32 = &H80
Const
FILE_FLAG_NO_BUFFERING As
Int32 = &H20000000
#End
Region
Next, we want to find the removable drives (floppies) on our system.
Private
Sub
DetectFloppyDrives()
Dim
diskClass As
New ManagementClass("Win32_LogicalDisk")
Dim
disks As
ManagementObjectCollection = diskClass.GetInstances()
Dim
disk As
ManagementObject
For
Each disk
In disks
If disk("drivetype").ToString
= "2"
Then
cboFloppy.Items.Add(disk("deviceid"))
Next
If cboFloppy.Items.Count = 0
Then
btnCreate.Enabled = False
MsgBox("This
program cannot function without a floppy drive.",
MsgBoxStyle.Information)
Exit Sub
End
If
cboFloppy.SelectedIndex = 0
'select first item in list
End
Sub
Then, we want to create our Image Subroutines (CreateImage & CreateDisk)
Private
Sub
CreateImage()
Dim
ImageName As
String
With SaveFileDialog1
.DefaultExt =
".fss"
.Filter =
"Floppy Snapshots (.fss)|*.fss|DD Disk
Images (.img)|*.img"
.FilterIndex =
0
.Title =
"Save Floppy Snapshot"
.ShowDialog(Me)
ImageName = .FileName
If ImageName = ""
Then
Exit
Sub
End
With
btnCreate.Enabled =
False
'read in increments of
18432 (80 tracks)
Dim
buf(18432) As
Byte
Dim fh
As IntPtr = CreateFile("\\.\"
& cboFloppy.Text, _
GENERIC_READ, _
FILE_SHARE_READ, _
IntPtr.Zero, _
OPEN_EXISTING, _
FILE_ATTRIBUTE_NORMAL Or
FILE_FLAG_NO_BUFFERING, _
0)
Dim
sw As
New FileStream(ImageName,
FileMode.Create)
With
ProgressBar1
.Minimum = 0
.Maximum = 80
.Value = 0
End
With
For i
As
Integer = 1
To 80
Dim y As
Int32
Dim x
As Int32 = ReadFile(fh, buf,
18432, y, IntPtr.Zero)
If x = 1
Then
sw.Write(buf, 0, 18432)
ProgressBar1.Value = i
Else
MsgBox("Bad Disk or No Disk in Drive.",
MsgBoxStyle.Critical)
Exit For
End
If
Application.DoEvents()
Next
CloseHandle(fh)
sw.Close()
ProgressBar1.Value = 0
btnCreate.Enabled =
True
End Sub
Private
Sub
CreateDisk()
Dim
ImageName As
String
With OpenFileDialog1
.FileName =
""
.DefaultExt =
".fss"
.Filter =
"Floppy Snapshots (.fss)|*.fss|DD Disk
Images (.img)|*.img"
.FilterIndex =
0
.Title =
"Choose Image File"
.ShowDialog(Me)
ImageName = .FileName
If ImageName = ""
Then
Exit
Sub
End
With
btnCreate.Enabled =
False
'write in increments of
18432 (80 tracks)
Dim
buf(18432) As
Byte
Dim fh
As IntPtr = CreateFile("\\.\"
& cboFloppy.Text, _
GENERIC_WRITE, _
FILE_SHARE_WRITE, _
IntPtr.Zero, _
OPEN_EXISTING, _
FILE_ATTRIBUTE_NORMAL Or
FILE_FLAG_NO_BUFFERING, _
0)
Dim
sr As
New FileStream(ImageName,
FileMode.Open)
With
ProgressBar1
.Minimum = 0
.Maximum = 80
.Value = 0
End
With
For i
As
Integer = 1
To 80
sr.Read(buf, 0, 18432)
Dim y
As Int32
Dim x As
Int32 = WriteFile(fh, buf, 18432, y, IntPtr.Zero)
If x = 1 Then
ProgressBar1.Value = i
Else
MsgBox("Bad Disk or No Disk
in Drive.", MsgBoxStyle.Critical)
Exit For
End
If
Application.DoEvents()
Next
CloseHandle(fh)
sr.Close()
ProgressBar1.Value = 0
btnCreate.Enabled =
True
End Sub
This will get the job done. How you design your interface & call the
routines is up to you. My finished program looks like this:
Download
the VB2005 Project