23 December 2008


For anyone trying to get IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER to work. The following would return an error about the buffer being too small, if the device supports the call, and if I haven't made a mistake. I get "The request is not supported", which seems to be what other folks are saying. It seems no USB Flash drives actually support this call, I've tried with a secure sandisk one.
Option Strict On
Option Explicit On
Option Infer Off

Imports Microsoft.Win32.SafeHandles
Imports System.Runtime.InteropServices
Imports System.ComponentModel

Public Class Form1


  <Flags()> _
  Private Enum AccessRights As UInteger
      GenericRead = &H80000000UI
      GenericWrite = &H40000000
      GenericExecute = &H20000000
      GenericAll = &H10000000
  End Enum

  <Flags()> _
  Private Enum ShareModes As UInteger
      FileShareRead = 1
      FileShareWrite = 2
      FileShareDelete = 4
  End Enum

  Private Enum CreationDisposition As UInteger
      CreateNew = 1
      CreateAlways = 2
      OpenExisting = 3
      OpenAlways = 4
      TruncateExisting = 5
  End Enum

  <StructLayout(LayoutKind.Sequential)> _
  Private Structure MediaSerialNumberData
      Public SerialNumberLength As UInteger
      Public Result As UInteger
      Public Reserved As UInt64
      Public SerialNumberData As Byte ' We would get the 1st byte, if any UFDs actually worked.
      Public Function Size() As Integer
          Return Marshal.SizeOf(Me)
      End Function
  End Structure

  <DllImport("kernel32", CharSet:=CharSet.Unicode, SetLastError:=True)> _
  Private Shared Function CreateFile( _
  ByVal fileName As String, _
  ByVal desiredAccess As AccessRights, _
  ByVal shareMode As ShareModes, _
  ByVal securityAttributes As IntPtr, _
  ByVal creationDisposition As CreationDisposition, _
  ByVal flagsAndAttributes As Integer, _
  ByVal hTemplateFile As IntPtr) As SafeFileHandle
  End Function

  <DllImport("kernel32", SetLastError:=True)> _
  Private Shared Function DeviceIoControl( _
  ByVal hVol As SafeFileHandle, _
  ByVal controlCode As UInteger, _
  ByVal inBuffer As IntPtr, _
  ByVal inBufferSize As Integer, _
  ByRef outBuffer As MediaSerialNumberData, _
  ByVal outBufferSize As Integer, _
  ByRef bytesReturned As Integer, _
  ByVal overlapped As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
  End Function

  Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
      Dim sfh As SafeFileHandle = Nothing
          sfh = CreateFile("//./H:", AccessRights.GenericRead, _
                           ShareModes.FileShareRead Or _
                           ShareModes.FileShareWrite, _
                           IntPtr.Zero, _
                           CreationDisposition.OpenExisting, _
                           0, IntPtr.Zero)
          Dim msnd As New MediaSerialNumberData
          Dim returned As Integer
          Dim result As Boolean = DeviceIoControl(sfh, IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER, _
                                                  IntPtr.Zero, 0, msnd, msnd.Size, returned, IntPtr.Zero)
          If result = False Then
              Console.WriteLine((New Win32Exception).Message)
          End If
      Catch ex As Exception
          If sfh IsNot Nothing Then
              If sfh.IsInvalid = False Then
                  If sfh.IsClosed = False Then
                  End If
              End If
          End If
      End Try

  End Sub

End Class

1 comment:

  1. Hmm...

    IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER 0x2d0c10 inc\api\ntddstor.h