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

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
 
J

Jay B. Harlow [MVP - Outlook]

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
 
S

Schorschi

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top