HDD シリアル番号 (モデル番号ではない) を取得するために、ネイティブCreateFile
と呼び出しを使用する 3 つの異なるメソッドを作成しました。DeviceIoControl
1 番目は を使用しS.M.A.R.T.
、2 番目は を使用Storage Query
し、3 番目は を使用しますSCSI PassThrough
。私のコードのほとんどは、このスレッドの内容に基づいています(いくつかの修正と改善が加えられています)。
diskid32 ユーティリティを使用して取得した結果は次のとおりです。
Trying to read the drive IDs using physical access with admin rights
Drive Model Number________________: [ST975XXXXX]
Drive Serial Number_______________: [ 6WS2XXXX]
Trying to read the drive IDs using physical access with zero rights
Product Id = [ST975XXXXX]
Serial Number = [6WS2XXXX]
Trying to read the drive IDs using Smart
Drive Model Number________________: [ST975XXXXX]
Drive Serial Number_______________: [ 6WS2XXXX]
さて、ここに私の方法を使用した結果があります:
S.M.A.R.T. = 6WS2XXXX
Storage Query = 6WS2XXXX
SCSI PassThrough = ST975XXXXX
ええと... ヒューストンはここで問題があります。最初の 2 つの方法で、正しいシリアル番号を取得できます。最後の 1 つでは、非常に悪いモデル番号を取得します。さて、ここに私のコードがあります:
--- METHOD ---
internal static String GetHardDiskSerialSCSIPassthrough(SafeFileHandle deviceHandle)
{
IntPtr bufferPointer = IntPtr.Zero;
String serial = String.Empty;
UInt32 bytesReturned;
SCSIPassthroughBuffered bspt = new SCSIPassthroughBuffered();
bspt.SPT.Length = (UInt16)Marshal.SizeOf(bspt.SPT);
bspt.SPT.CommandDescriptorBlockLength = 16;
bspt.SPT.DataIn = 0x1;
bspt.SPT.DataTransferLength = 64;
bspt.SPT.DataBufferOffset = new IntPtr(Marshal.SizeOf(bspt) - 64);
bspt.SPT.TimeOutValue = 60;
bspt.SPT.CommandDescriptorBlock = new Byte[] { 0x12, 0x1, 0x80, 0x0, 64, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
Int32 bufferSize = Marshal.SizeOf(bspt);
try
{
bufferPointer = Marshal.AllocHGlobal(bufferSize);
Marshal.StructureToPtr(bspt, bufferPointer, true);
if (DeviceIoControl(deviceHandle, 0x4D004, bufferPointer, (UInt32)bufferSize, bufferPointer, (UInt32)bufferSize, out bytesReturned, IntPtr.Zero) && (bytesReturned > 0))
{
SCSIPassthroughBuffered result = (SCSIPassthroughBuffered)Marshal.PtrToStructure(bufferPointer, typeof(SCSIPassthroughBuffered));
serial = Encoding.ASCII.GetString(result.Buffer, 0, result.Buffer.Length).Replace("\0", String.Empty).Trim();
}
}
finally
{
Marshal.FreeHGlobal(bufferPointer);
}
return serial;
}
--- STRUCTURES ---
[StructLayout(LayoutKind.Sequential)]
private struct SCSIPassthrough
{
public UInt16 Length;
public Byte SCSIStatus;
public Byte PathID;
public Byte TargetID;
public Byte LogicalUnitNumber;
public Byte CommandDescriptorBlockLength;
public Byte SenseInfoLength;
public Byte DataIn;
public UInt32 DataTransferLength;
public UInt32 TimeOutValue;
public IntPtr DataBufferOffset;
public UInt32 SenseInfoOffset;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public Byte[] CommandDescriptorBlock;
}
[StructLayout(LayoutKind.Sequential)]
private struct SCSIPassthroughBuffered
{
public SCSIPassthrough SPT;
public UInt32 Filler;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
public Byte[] Buffer;
}
私は何を間違っていますか?間違ったCDBを使用している可能性がありますか?