DeviceIoControl

psalm1975

New member
Joined
Nov 18, 2008
Messages
1
Programming Experience
Beginner
I have been trying to write a VB.net program with VB 2008 Express on Win7 to issue an IDENTIFY DEVICE ATA command to a drive.

Here is what I have got so far. But it is still not working
whenever I call the DeviceIoControl, it always return false.
Anyone know what I am doing wrong?

Please advice

Thanks



Imports System
Imports System.Text
Imports System.Runtime.InteropServices
Imports System.Security.Permissions

Public Class Form1


    Private Structure ATA_PASS_THROUGH_EX_WITH_BUFFERS
        Public Apt As ATA_PASS_THROUGH_EX

        Public Data() As Byte
    End Structure

    Private Structure ATA_PASS_THROUGH_EX
        Public Length As Short
        Public AtaFlags As Short
        Public PathId As Byte
        Public TargetId As Byte
        Public Lun As Byte
        Public ReservedAsUchar As Byte
        Public DataTransferLength As Integer
        Public TimeOutValue As Integer
        Public ReservedAsUlong As Integer
        Public DataBufferOffset As IntPtr

        Public PreviousTaskFile() As Byte

        Public CurrentTaskFile() As Byte
    End Structure


    Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal FileName As String, ByVal DesiredAccess As Integer, ByVal ShareMode As Integer, ByVal SecurityAttributes As IntPtr, ByVal CreationDisposition As Integer, ByVal FlagsAndAttributes As Integer, ByVal hTemplateFile As IntPtr) As Long
    Private Declare Function DeviceIoControl Lib "kernel32" (ByVal deviceHandleas As Long, ByVal controlCode As Integer, ByRef inBuffer As ATA_PASS_THROUGH_EX_WITH_BUFFERS, ByVal inBufferSize As Integer, ByRef outBuffer As ATA_PASS_THROUGH_EX_WITH_BUFFERS, ByVal outBufferSize As Integer, ByRef bytesReturned As Integer, ByVal overlapped1 As IntPtr) As Boolean


    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim letter As Char = "E"
        Console.WriteLine()
        Const GenericRead As Integer = &H80000000
        Const GenericWrite As Integer = &H40000000
        Const FileShareRead As Integer = 1
        Const FileShareWrite As Integer = 2
        Const OpenExisting As Integer = 3
        Dim drivePath As String = String.Concat("\\.\" & letter & ":")
        Console.WriteLine("Trying path: " & drivePath)
        Dim driveHandle = CreateFile(drivePath, GenericRead Or GenericWrite, FileShareRead Or FileShareWrite, IntPtr.Zero, OpenExisting, 0, IntPtr.Zero)
        
        Dim apex As New ATA_PASS_THROUGH_EX
        apex.Length = Marshal.SizeOf(apex)
        apex.AtaFlags = 2 ' ATA_FLAGS_DATA_IN
        apex.DataTransferLength = 512 ' The command returns a 512 byte package of info.
        apex.TimeOutValue = 10 ' 10 second timeout.
        apex.DataBufferOffset = Marshal.OffsetOf(GetType(ATA_PASS_THROUGH_EX_WITH_BUFFERS), "Data")
        apex.CurrentTaskFile = New Byte(7) {} ' This contains the command we are requesting.
        apex.CurrentTaskFile(6) = &HEC        ' <-- the command "IDENTIFY DEVICE"
        Dim apexb As New ATA_PASS_THROUGH_EX_WITH_BUFFERS
        apexb.Apt = apex
        Dim inBufferSize As Integer = Marshal.SizeOf(GetType(ATA_PASS_THROUGH_EX_WITH_BUFFERS))
        Dim bytesReturned As Integer
        Const IOCTL_ATA_PASS_THROUGH As Integer = &H4D02C
        Dim result As Boolean = DeviceIoControl(driveHandle, IOCTL_ATA_PASS_THROUGH, _
            apexb, inBufferSize, apexb, inBufferSize, bytesReturned, IntPtr.Zero)
        If result = False Then
            Console.WriteLine("DeviceIOControl ERROR: ")
            Return
        End If
        
        Console.WriteLine("Press any key")
        Console.ReadKey()

    End Sub

End Class
 

Attachments

  • test2.zip
    14.6 KB · Views: 18
Last edited by a moderator:
Back
Top