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

I would change

Dim drivePath As String = String.Concat("\\.\" & letter & ":")

to

Dim drivePath As String = String.Concat(letter & ":")

or use the CreateFileW instead with

Dim drivePath As String = String.Concat("\\?\" & letter & ":")

Hope this helps

try this
Dim drivePath As String = "C:\Users\xxx\Desktop\x.txt"
Create file x.txt at desktop manually for first test
Worked to me but
Dim result As Boolean = DeviceIoControl(driveHandle, IOCTL_ATA_PASS_THROUGH, apexb, inBufferSize, apexb, inBufferSize, bytesReturned, IntPtr.Zero)
Still wrong

This article has been dead for over six months. Start a new discussion instead.