酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

Windows Mobile(.NET Compact Framework)でKernelIoControl関数を使って、デバイスのID(シリアル番号)を取得する

今回はデバイスのシリアル番号を取得する方法をご紹介します。

KernelIoControl 関数を使用して、デバイスIDまたはシリアル番号を取得する事が出来ます。

サンプルコードを以下に示します。

ネイティブ関数とやり取りする為の構造体を定義

   // 以下の名前空間を指定しておいてください
   // Imports System.Runtime.InteropServices
   Private Shared METHOD_BUFFERED As Int32 = 0
   Private Shared FILE_ANY_ACCESS As Int32 = 0
   Private Shared FILE_DEVICE_HAL As Int32 = &H101
   
   Private Const ERROR_NOT_SUPPORTED As Int32 = &H32
   Private Const ERROR_INSUFFICIENT_BUFFER As Int32 = &H7A
   
   Private Shared IOCTL_HAL_GET_DEVICEID As Int32 = _
       (&H10000 * FILE_DEVICE_HAL) Or (&H4000 * FILE_ANY_ACCESS) _
       Or (&H4 * 21) Or METHOD_BUFFERED
   
   <DllImport("CoreDll.dll")> _
   Private Shared Function KernelIoControl( _
       ByVal dwIoControlCode As Int32, _
       ByVal lpInBuf As IntPtr, _
       ByVal nInBufSize As Int32, _
       ByVal lpOutBuf() As Byte, _
       ByVal nOutBufSize As Int32, _
       ByRef lpBytesReturned As Int32) As Boolean
   End Function

デバイスのID(シリアル番号)を取得する

   Private Shared Function GetDeviceID() As String
   
       ' Initialize the output buffer to the size of a
       ' Win32 DEVICE_ID structure
       Dim outbuff(19) As Byte
       Dim dwOutBytes As Int32
       Dim done As Boolean = False
   
       Dim nBuffSize As Int32 = outbuff.Length
   
       ' Set DEVICEID.dwSize to size of buffer.  Some platforms look at
       ' this field rather than the nOutBufSize param of KernelIoControl
       ' when determining if the buffer is large enough.
       BitConverter.GetBytes(nBuffSize).CopyTo(outbuff, 0)
       dwOutBytes = 0
   
       ' Loop until the device ID is retrieved or an error occurs.
       While Not done
           If KernelIoControl(IOCTL_HAL_GET_DEVICEID, IntPtr.Zero, _
               0, outbuff, nBuffSize, dwOutBytes) Then
               done = True
           Else
               Dim errnum As Integer = Marshal.GetLastWin32Error()
               Select Case errnum
                   Case ERROR_NOT_SUPPORTED
                       Throw New NotSupportedException( _
                           "IOCTL_HAL_GET_DEVICEID is not supported on this device", _
                           New System.ComponentModel.Win32Exception(errnum))
   
                   Case ERROR_INSUFFICIENT_BUFFER
   
                       ' The buffer is not big enough for the data.  The
                       ' required size is in the first 4 bytes of the output
                       ' buffer (DEVICE_ID.dwSize).
                       nBuffSize = BitConverter.ToInt32(outbuff, 0)
                       outbuff = New Byte(nBuffSize) {}
   
                       ' Set DEVICEID.dwSize to size of buffer.  Some
                       ' platforms look at this field rather than the
                       ' nOutBufSize param of KernelIoControl when
                       ' determining if the buffer is large enough.
                       BitConverter.GetBytes(nBuffSize).CopyTo(outbuff, 0)
   
                   Case Else
                       Throw New System.ComponentModel.Win32Exception(errnum, "Unexpected error")
               End Select
           End If
       End While
   
       ' Copy the elements of the DEVICE_ID structure.
       Dim dwPresetIDOffset As Int32 = BitConverter.ToInt32(outbuff, &H4)
       Dim dwPresetIDSize As Int32 = BitConverter.ToInt32(outbuff, &H8)
       Dim dwPlatformIDOffset As Int32 = BitConverter.ToInt32(outbuff, &HC)
       Dim dwPlatformIDSize As Int32 = BitConverter.ToInt32(outbuff, &H10)
       Dim sb As New System.Text.StringBuilder
       Dim i As Integer
   
       For i = dwPresetIDOffset To (dwPresetIDOffset + dwPresetIDSize) - 1
           sb.Append(String.Format("{0:X2}", outbuff(i)))
       Next i
   
       sb.Append("-")
   
       For i = dwPlatformIDOffset To (dwPlatformIDOffset + dwPlatformIDSize) - 1
           sb.Append(String.Format("{0:X2}", outbuff(i)))
       Next i
   
       Return sb.ToString()
   End Function