Can't seemd to get ReadFile API to work! Returns invalid handle error?

  • Thread starter Thread starter Schorschi
  • Start date Start date
S

Schorschi

Can't seemd to get ReadFile API to work! Returns invalid handle
error?
===========================================================================
Ok, the visual basic gurus, help!

The following is a diskette class (vb .net) that works find, in that I
can validate a diskette is mounted, dismount it, lock it, unlock it,
get diskette geometry, etc., all with a valid handle from CreateFile
API! I can even position the file pointer, BUT... When I try to
read the disk sector... BANG I get an invaild handle error from the
ReadFile API call? And yes, I am trying to read a Bytes-Per-Sector
size length, i.e. 512. Help!

Option Explicit On
Option Strict On

'

Imports System.Runtime.InteropServices.Marshal
Imports System.Reflection.Assembly
Imports System.Runtime.InteropServices

'

Public Class DisketteClass

'

Public Const DISKETTE_ONE As String = "\\.\A:", _
DISKETTE_TWO As String = "\\.\B:"

Private Const GENERIC_WRITE As Integer = &H40000000, _
GENERIC_READ As Integer = &H80000000

Private Const OPEN_EXISTING As Integer = &H3

Private Const SHARE_WRITE As Integer = &H2, _
SHARE_READ As Integer = &H1

Private Const FILE_BEGIN As Integer = 0, _
FILE_CURRENT As Integer = 1, _
FILE_END As Integer = 2

Private Const ATTRIBUTE_NO_BUFFERING As Integer = &H20000000, _
ATTRIBUTE_SYSTEM As Integer = &H4, _
ATTRIBUTE_NORMAL As Integer = &H80

Private Const FILE_DEVICE_FILE_SYSTEM As Integer = &H9, _
METHOD_BUFFERED As Integer = 0, _
FILE_ANY_ACCESS As Integer = 0, _
FILE_DEVICE_DISK As Integer = &H7

Private Const INVALID_SET_FILE_POINTER As Integer = -1

Private Const IOCTL_DISK_BASE As Integer = FILE_DEVICE_DISK

'

Public Enum DiskettePosition

'

Absolute = 0
Logical = 1

End Enum

'

<StructLayout(LayoutKind.Explicit)> _
Public Structure _LARGE_INTEGER

'

<FieldOffset(0)> Dim theLow As Integer
<FieldOffset(4)> Dim theHigh As Integer
<FieldOffset(0)> Dim theQuad As Long

End Structure

<StructLayout(LayoutKind.Sequential)> _
Public Structure _DISK_GEOMETRY

'

Dim theCylinders As _LARGE_INTEGER, _
theMediaType As MediaType, _
theTracksPerCylinder As Integer, _
theSectorsPerTrack As Integer, _
theBytesPerSector As Integer

End Structure

'

Public Enum DisketteError

' Windows API Tape Error(s)...

Success = 0& ' ERROR_SUCCESS
ReadFault = 30& ' ERROR_READ_FAULT
NotSupported = 50& ' ERROR_NOT_SUPPORTED
WriteProtect = 19& ' ERROR_WRITE_PROTECT
MoreData = 234& ' ERROR_MORE_DATA
InValidFunction = 1& ' ERROR_INVALID_FUNCTION
FileNotFound = 2& ' ERROR_FILE_NOT_FOUND
BadUnit = 20& ' ERROR_BAD_UNIT
WriteFault = 29& ' ERROR_WRITE_FAULT
NotReady = 21& ' ERROR_NOT_READY
CyclicRedundencyCheck = 23& ' ERROR_CRC

End Enum

Public Enum MediaType

'

Unknown
F5_1Pt2_512 ' 5.25", 1.2MB, 512 bytes/sector
F3_1Pt44_512 ' 3.5", 1.44MB, 512 bytes/sector
F3_2Pt88_512 ' 3.5", 2.88MB, 512 bytes/sector
F3_20Pt8_512 ' 3.5", 20.8MB, 512 bytes/sector
F3_720_512 ' 3.5", 720KB, 512 bytes/sector
F5_360_512 ' 5.25", 360KB, 512 bytes/sector
F5_320_512 ' 5.25", 320KB, 512 bytes/sector
F5_320_1024 ' 5.25", 320KB, 1024 bytes/sector
F5_180_512 ' 5.25", 180KB, 512 bytes/sector
F5_160_512 ' 5.25", 160KB, 512 bytes/sector
RemovableMedia ' Removable media other than floppy
FixedMedia ' Fixed hard disk media
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

End Enum

'

Private Structure DisketteStructure

'

Dim theGeometry As _DISK_GEOMETRY, _
theHandle As IntPtr, _
thePath As String, _
theResult As Integer

End Structure

'

<DllImport("KERNEL32.DLL", _
EntryPoint:="SetFilePointer", _
SetLastError:=True, _
CharSet:=CharSet.Auto, _
ExactSpelling:=True, _
CallingConvention:=CallingConvention.StdCall)> _
Private Shared Function SetFilePointer _
(ByVal theHandle As IntPtr, ByVal theLow As Int32, ByRef
theHigh As Int32, ByVal theMode As Int32) As Int32

'

End Function

<DllImport("KERNEL32.DLL", _
EntryPoint:="DeviceIoControl", _
SetLastError:=True, _
CharSet:=CharSet.Auto, _
ExactSpelling:=True, _
CallingConvention:=CallingConvention.StdCall)> _
Private Shared Function DeviceIoControl _
(ByVal theHandle As IntPtr, ByVal theCode As Int32, ByVal
theIn As IntPtr, ByVal theInLength As Int32, <Out()> ByVal theOut As
IntPtr, ByVal theOutSize As Int32, ByRef theSize As Int32, ByVal
theOverLapped As IntPtr) As Boolean

'

End Function

<DllImport("KERNEL32.DLL", _
EntryPoint:="CreateFileW", _
SetLastError:=True, _
CharSet:=CharSet.Unicode, _
ExactSpelling:=True, _
CallingConvention:=CallingConvention.StdCall)> _
Private Shared Function CreateFile _
(ByVal thePath As String, ByVal theAccess As Integer, ByVal
theMode As Integer, ByVal theAttributes As Integer, ByVal
theDisposition As Integer, ByVal theFlag As Integer, ByVal theTemplate
As Integer) As IntPtr

'

End Function

<DllImport("KERNEL32.DLL", _
EntryPoint:="CloseHandle", _
SetLastError:=True, _
CharSet:=CharSet.Auto, _
ExactSpelling:=True, _
CallingConvention:=CallingConvention.StdCall)> _
Private Shared Function CloseHandle _
(ByVal theHandle As IntPtr) As Boolean

'

End Function

<DllImport("KERNEL32.DLL", _
EntryPoint:="ReadFile", _
SetLastError:=True, _
CharSet:=CharSet.Auto, _
ExactSpelling:=True, _
CallingConvention:=CallingConvention.StdCall)> _
Private Shared Function ReadFile _
(ByVal theHandle As IntPtr, ByVal theData As Byte(), ByVal
theSize As Integer, ByRef theLength As Integer, ByRef theOverlapped As
Integer) As Boolean

'

End Function

<DllImport("KERNEL32.DLL", _
EntryPoint:="WriteFile", _
SetLastError:=True, _
CharSet:=CharSet.Auto, _
ExactSpelling:=True, _
CallingConvention:=CallingConvention.StdCall)> _
Private Shared Function WriteFile _
(ByVal theHandle As IntPtr, ByVal theData As Byte(), ByVal
theSize As Integer, ByRef theLength As Integer, ByRef theOverlapped As
Integer) As Boolean

'

End Function

Private theDiskette As DisketteStructure

'

Public Sub New(Optional ByVal thePath As String = DISKETTE_ONE)

'

With theDiskette

'

.thePath = thePath

Open()
Geometry()

End With

End Sub

Public Sub Dispose()

'

Close()

End Sub

Public Function Position(ByVal thePosition As Integer, Optional
ByVal theMode As DiskettePosition = DiskettePosition.Logical) As
Boolean

Dim thePositionOrNot As Boolean, _
theDistance As Integer

'

With theDiskette

'

With .theGeometry

'

thePosition = CInt(IIf(theMode <> _
DiskettePosition.Logical, thePosition, thePosition
* .theBytesPerSector))

End With

'

thePosition = SetFilePointer _
(.theHandle, thePosition, theDistance, FILE_BEGIN)

Select Case (thePosition)

Case INVALID_SET_FILE_POINTER

'

thePositionOrNot = False

.theResult = GetLastWin32Error()

Case Else

'

thePositionOrNot = True

End Select

End With

Return (thePositionOrNot)

End Function

Public Function Read(ByVal theData As Byte()) As Boolean

Dim theReadOrNot As Boolean, _
theSize As Integer, _
theLength As Integer

'

With theDiskette

'

theReadOrNot = ReadFile _
(.theHandle, theData, theLength, theSize, Nothing)

Select Case (theReadOrNot And (Not (theLength <>
theSize)))

Case True

'

Case False

'

.theResult = GetLastWin32Error()

theReadOrNot = False

End Select

End With

Return (theReadOrNot)

End Function

Public Function Write(ByVal theData As Byte()) As Boolean

'

End Function

Public Function Geometry() As Boolean

Dim theGeometryOrNot As Boolean, _
theBuffer As IntPtr, _
theSize As Integer, _
theLength As Integer

'

With theDiskette

'

theLength = SizeOf(.theGeometry)

theBuffer = Marshal. _
AllocHGlobal(theLength)

' IOCTL_DISK_GET_DRIVE_GEOMETRY (&H70000)...

theGeometryOrNot = DeviceIoControl(.theHandle,
ControlCode(IOCTL_DISK_BASE, 0, _
METHOD_BUFFERED, FILE_ANY_ACCESS), IntPtr.Zero,
Nothing, theBuffer, theLength, theSize, IntPtr.Zero)

Select Case (theGeometryOrNot)

Case True

'

.theGeometry = CType(Marshal.PtrToStructure _
(theBuffer, GetType(_DISK_GEOMETRY)),
_DISK_GEOMETRY)

Case False

'

.theResult = GetLastWin32Error()

End Select

'

Marshal. _
FreeHGlobal(theBuffer)

End With

End Function

Public Function Open() As Integer

'

With theDiskette

'

.theHandle = CreateFile(.thePath, GENERIC_READ Or
GENERIC_WRITE, _
SHARE_READ Or SHARE_WRITE, Nothing, OPEN_EXISTING,
ATTRIBUTE_NORMAL, Nothing)

If (IsNotHandle(.theHandle)) Then

'

.theResult = GetLastWin32Error()

End If

End With

'

Return (Result)

End Function

Public Function Close() As Integer

'

With theDiskette

'

Select Case (CloseHandle(.theHandle))

Case True

'

.theResult = DisketteError. _
Success

Case False

'

.theResult = GetLastWin32Error()

End Select

.theHandle = Nothing

End With

'

Return (Result)

End Function

Public ReadOnly Property Path() As String

Get

'

With theDiskette

'

Return (.thePath)

End With

End Get

End Property

Public ReadOnly Property Result() As Integer

Get

'

With theDiskette

'

Return (.theResult)

End With

End Get

End Property

Public ReadOnly Property Cylinders() As _LARGE_INTEGER

Get

'

With theDiskette

'

With .theGeometry

'

Return (.theCylinders)

End With

End With

End Get

End Property

Public ReadOnly Property Type() As MediaType

Get

'

With theDiskette

'

With .theGeometry

'

Return (.theMediaType)

End With

End With

End Get

End Property

Public ReadOnly Property BytesPerSector() As Integer

Get

'

With theDiskette

'

With .theGeometry

'

Return (.theBytesPerSector)

End With

End With

End Get

End Property

Public ReadOnly Property SectorsPerTrack() As Integer

Get

'

With theDiskette

'

With .theGeometry

'

Return (.theSectorsPerTrack)

End With

End With

End Get

End Property

Public ReadOnly Property TracksPerCylinder() As Integer

Get

'

With theDiskette

'

With .theGeometry

'

Return (.theTracksPerCylinder)

End With

End With

End Get

End Property

Public ReadOnly Property Size() As Long

Get

'

With theDiskette

'

With .theGeometry

'

Return (.theTracksPerCylinder * _
.theSectorsPerTrack * .theBytesPerSector *
..theCylinders.theQuad)

End With

End With

End Get

End Property

Public Function Mount() As Boolean

'

End Function

Public Function UnMount() As Boolean

Dim theUnMountOrNot As Boolean, _
theSize As Integer

'

With theDiskette

' FSCTL_DISMOUNT_VOLUME...

theUnMountOrNot = DeviceIoControl(.theHandle,
ControlCode(FILE_DEVICE_FILE_SYSTEM, _
8, METHOD_BUFFERED, FILE_ANY_ACCESS), Nothing,
Nothing, Nothing, Nothing, theSize, Nothing)

Select Case (theUnMountOrNot)

Case True

'

Case False

'

.theResult = GetLastWin32Error()

End Select

End With

Return (theUnMountOrNot)

End Function

Public Function Lock() As Boolean

Dim theLockOrNot As Boolean, _
theSize As Integer

'

With theDiskette

' FSCTL_LOCK_VOLUME...

theLockOrNot = DeviceIoControl(.theHandle,
ControlCode(FILE_DEVICE_FILE_SYSTEM, _
6, METHOD_BUFFERED, FILE_ANY_ACCESS), Nothing,
Nothing, Nothing, Nothing, theSize, Nothing)

Select Case (theLockOrNot)

Case True

'

Case False

'
.theResult = GetLastWin32Error()

End Select

End With

Return (theLockOrNot)

End Function

Public Function UnLock() As Boolean

Dim theUnLockOrNot As Boolean, _
theSize As Integer

'

With theDiskette

' FSCTL_UNLOCK_VOLUME...

theUnLockOrNot = DeviceIoControl(.theHandle,
ControlCode(FILE_DEVICE_FILE_SYSTEM, _
7, METHOD_BUFFERED, FILE_ANY_ACCESS), Nothing,
Nothing, Nothing, Nothing, theSize, Nothing)

Select Case (theUnLockOrNot)

Case True

'

Case False

'

.theResult = GetLastWin32Error()

End Select

End With

Return (theUnLockOrNot)

End Function

Public Function IsMount() As Boolean

Dim theIsOrNot As Boolean, _
theSize As Integer

'

With theDiskette

' FSCTL_IS_VOLUME_MOUNTED...

theIsOrNot = DeviceIoControl(.theHandle,
ControlCode(FILE_DEVICE_FILE_SYSTEM, _
10, METHOD_BUFFERED, FILE_ANY_ACCESS), Nothing,
Nothing, Nothing, Nothing, theSize, Nothing)

Select Case (theIsOrNot)

Case True

'

Case False

'

.theResult = GetLastWin32Error()

End Select

End With

Return (theIsOrNot)

End Function

Private Function ControlCode(ByVal theDevice As Integer, ByVal
theFunction As Integer, ByVal theMethod As Integer, ByVal theAccess As
Integer) As Integer

'

Return (CInt(theDevice * (2 ^ 16)) Or CInt _
(theAccess * (2 ^ 14)) Or CInt(theFunction * (2 ^ 2)) Or
theMethod)

End Function

End Class
 
Schorschi,
You may want to ask this question "down the hall" in the
microsoft.public.dotnet.framework.interop newsgroup, as that is where most,
if not all, the programmers who use interop a lot hang out.
Return (CInt(theDevice * (2 ^ 16)) Or CInt _
(theAccess * (2 ^ 14)) Or CInt(theFunction * (2 ^ 2)) Or
theMethod)

BTW: If you are using VB.NET 2003 you may want to consider using the new bit
shift operators, as they are more efficient then relaying on the
exponentiation operator & converting to & from doubles.

' VS.NET 2003 syntax
Return (theDevice << 16) Or (theAccess << 14) Or (theFunction << 2) Or
(theMethod)

Hope this helps
Jay
 
Actually, the ReadFile API works! I had a problem elsewhere in my
code. Nuts. Thanks for the Bit Operator comment. Coming from a ASM
and C background, I find VB a little odd to work in at times. Funny
how coming from a C background (hard C not C# or C++) makes VB (or
..NET) a pain at times.

Thx.
 
Back
Top