I have been trying to write a simple program to issue Identify device ATA command to a drive with VB 2008 express, and has so far been unsuccessful
Below are the code I have so far. But everytime I call the DeviceIOControl, it always return false. Can someone tell me what I am doing wrong?
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