详细如下:
type
_STORAGE_DEVICE_DESCRIPTOR = record
Version: LongInt; // 版本
Size: LongInt; // 结构大小
DeviceType: Char; // 设备类型
DeviceTypeModifier: Char; // SCSI-2额外的设备类型
RemovableMedia: BOOLEAN; // 是否可移动
CommandQueueing: BOOLEAN; // 是否支持命令队列
VendorIdOffset: LongInt; // 厂家设定值的偏移
ProductIdOffset: LongInt; // 产品ID的偏移
ProductRevisionOffset: LongInt; // 产品版本的偏移
SerialNumberOffset: LongInt; // 序列号的偏移
BusType: STORAGE_BUS_TYPE; // 总线类型
RawPropertiesLength: longInt; // 额外的属性数据长度
RawDeviceProperties: array[1..1] of Char; // 额外的属性数据(仅定义了象征性的1个字节)
end;
STORAGE_DEVICE_DESCRIPTOR = _STORAGE_DEVICE_DESCRIPTOR;
PSTORAGE_DEVICE_DESCRIPTOR = ^STORAGE_DEVICE_DESCRIPTOR;
pDevDesc: PSTORAGE_DEVICE_DESCRIPTOR; DeviceIoControl(hDevice, // 设备句柄
IOCTL_STORAGE_QUERY_PROPERTY, // 取设备属性信息
@Query, sizeof(STORAGE_PROPERTY_QUERY), // 输入数据缓冲区
pDevDesc, pDevDesc.Size, // 输出数据缓冲区
dwOutBytes, // 输出数据长度
nil);
上面的代码读取了STORAGE_DEVICE_DESCRIPTOR,也可取得该结构中的DeviceType值,我想问如何取得其serialnumber,因为
该结构中定义的是serialnumberoffset。谢谢
type
_STORAGE_DEVICE_DESCRIPTOR = record
Version: LongInt; // 版本
Size: LongInt; // 结构大小
DeviceType: Char; // 设备类型
DeviceTypeModifier: Char; // SCSI-2额外的设备类型
RemovableMedia: BOOLEAN; // 是否可移动
CommandQueueing: BOOLEAN; // 是否支持命令队列
VendorIdOffset: LongInt; // 厂家设定值的偏移
ProductIdOffset: LongInt; // 产品ID的偏移
ProductRevisionOffset: LongInt; // 产品版本的偏移
SerialNumberOffset: LongInt; // 序列号的偏移
BusType: STORAGE_BUS_TYPE; // 总线类型
RawPropertiesLength: longInt; // 额外的属性数据长度
RawDeviceProperties: array[1..1] of Char; // 额外的属性数据(仅定义了象征性的1个字节)
end;
STORAGE_DEVICE_DESCRIPTOR = _STORAGE_DEVICE_DESCRIPTOR;
PSTORAGE_DEVICE_DESCRIPTOR = ^STORAGE_DEVICE_DESCRIPTOR;
pDevDesc: PSTORAGE_DEVICE_DESCRIPTOR; DeviceIoControl(hDevice, // 设备句柄
IOCTL_STORAGE_QUERY_PROPERTY, // 取设备属性信息
@Query, sizeof(STORAGE_PROPERTY_QUERY), // 输入数据缓冲区
pDevDesc, pDevDesc.Size, // 输出数据缓冲区
dwOutBytes, // 输出数据长度
nil);
上面的代码读取了STORAGE_DEVICE_DESCRIPTOR,也可取得该结构中的DeviceType值,我想问如何取得其serialnumber,因为
该结构中定义的是serialnumberoffset。谢谢
TIdSector=packed record
wGenConfig:Word;
wNumCyls:Word;
wReserved:Word;
wNumHeads:Word;
wBytesPerTrack:Word;
wBytesPerSector:Word;
wSectorsPerTrack:Word;
wVendorUnique:array[0..2] of Word;
sSerialNumber:array[0..19] of char;
wBufferType:Word;
wBufferSize:Word;
wECCSize:Word;
sFirmwareRev:array[0..7] of char;
sModelNumber:array[0..39] of char;
wMoreVendorUnique:Word;
wDoubleWordIO:Word;
wCapabilities:Word;
wReserved1:Word;
wPIOTiming:Word;
wDMATiming:Word;
wBS:Word;
wNumCurrentCyls:Word;
wNumCurrentHeads:Word;
wNumCurrentSectorsPerTrack:Word;
ulCurrentSectorCapacity:ULONG;
wMultSectorStuff:Word;
ulTotalAddressableSectors:ULONG;
wSingleWordDMA:Word;
wMultiWordDMA:Word;
bReserved:array[0..127] of Byte;
end;
PIdSector=^TIdSector;
IDEREGS = record
bFeaturesReg :BYTE; // Used for specifying SMART "commands".
bSectorCountReg :BYTE; // IDE sector count register
bSectorNumberReg:BYTE; // IDE sector number register
bCylLowReg :BYTE; // IDE low order cylinder value
bCylHighReg :BYTE; // IDE high order cylinder value
bDriveHeadReg :BYTE; // IDE drive/head register
bCommandReg :BYTE; // Actual IDE command.
bReserved :BYTE; // reserved for future use. Must be zero.
end;
SENDCMDINPARAMS = record
cBufferSize :DWORD;
irDriveRegs :IDEREGS;
bDriveNumber:BYTE;
bReserved :Array[0..2] of BYTE;
dwReserved :Array[0..3] of DWORD;
bBuffer :BYTE;
end;
DRIVERSTATUS = record
bDriverError:BYTE;
bIDEStatus :BYTE;
bReserved :Array[0..1] of BYTE;
dwReserved :Array[0..1] of DWORD;
end;
SENDCMDOUTPARAMS = record
cBufferSize :DWORD;
DriverStatus:DRIVERSTATUS;
bBuffer :BYTE;
end;
PSENDCMDOUTPARAMS = ^SENDCMDOUTPARAMS;
// ·ÖÇøÀ©Õ¹ÐÅÏ¢
TDiskExtent = record
DiskNumber: Cardinal;
StartingOffset: LARGE_INTEGER;
ExtentLength: LARGE_INTEGER;
end;
DISK_EXTENT = TDiskExtent;
PDiskExtent = ^TDiskExtent; TVolumeDiskExtents = record
NumberOfDiskExtents: Cardinal;
Extents: array [0..0] of TDiskExtent;
end;
VOLUME_DISK_EXTENTS = TVolumeDiskExtents;
PVolumeDiskExtents = ^TVolumeDiskExtents;
function GetDiskInformation(byNumber: BYTE):String;
function GetVolumeInfo(DriverLetter: Char; var DiskExtent: TDiskExtent): Integer;implementationprocedure ChangeByteOrder(var Data;Size:Integer);
var
ptr:PChar;
I:Integer;
c:char;
begin
ptr:=@Data;
for I:=0 to(Size shr 1)-1 do
begin
c:=ptr^;
ptr^:=(ptr+1)^;
(ptr+1)^:=c;
Inc(ptr,2);
end;
end;
function GetDiskInformation(byNumber: BYTE): String;
var
hDevice:THandle;
cbBytesReturned:Dword;
s :String;
scip :SENDCMDINPARAMS;
OutCmd :SENDCMDOUTPARAMS;
IdOutCmd:Array[0..sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1] of BYTE;begin
result:='';
if Win32Platform=VER_PLATFORM_WIN32_NT then
begin// Windows NT, Windows 2000
// Get SCSI port handle
hDevice:=CreateFile(PChar('\\.\PhysicalDrive'+Inttostr(byNumber)),
GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE,
nil,
OPEN_EXISTING,
0,
0);
end
else
hDevice:=CreateFile('\\.\SMARTVSD',0,0,nil,CREATE_NEW,0,0); if hDevice=INVALID_HANDLE_VALUE then
Exit;
FillChar(scip, 0, sizeof(scip));
FillChar(OutCmd, 0, sizeof(OutCmd));
scip.cBufferSize := IDENTIFY_BUFFER_SIZE;
scip.irDriveRegs.bFeaturesReg := 0;
scip.irDriveRegs.bSectorCountReg := 1;
scip.irDriveRegs.bSectorNumberReg := 1;
scip.irDriveRegs.bCylLowReg := 0;
scip.irDriveRegs.bCylHighReg := 0; scip.irDriveRegs.bDriveHeadReg := $A0;// | ((bDriveNum & 1) << 4); scip.irDriveRegs.bCommandReg := IDE_ID_FUNCTION;
scip.bDriveNumber := 0;//bDriveNum;
scip.cBufferSize := IDENTIFY_BUFFER_SIZE; try
if not DeviceIoControl(hDevice,
DFP_RECEIVE_DRIVE_DATA,
@scip, sizeof(SENDCMDINPARAMS) - 1,
@IdOutCmd, sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
cbBytesReturned,nil) then Exit; finally
CloseHandle(hDevice);
end;
with PIdSector(@PSENDCMDOUTPARAMS(@IdOutCmd[0]).bBuffer)^ do
begin
ChangeByteOrder(sModelNumber, sizeof(sModelNumber));
ChangeByteOrder(sSerialNumber,SizeOf(sSerialNumber)); ChangeByteOrder(sFirmwareRev, sizeof(sFirmwareRev)); SetString(result,sModelNumber,SizeOf(sModelNumber));
SetString(s,sSerialNumber,SizeOf(sSerialNumber));
Result := Trim(Result)+'|'+Trim(s)+'|'+Trim(sFirmwareRev);
end;
end;
function GetVolumeInfo(DriverLetter: Char; var DiskExtent: TDiskExtent): Integer;
var
hVolume: THandle;
DiskExtents: PVolumeDiskExtents;
dwOutBytes: Cardinal;
begin
Result := -1;
hVolume := CreateFile(PChar('\\.\'+DriverLetter+':'), GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
if hVolume < 1 then
Exit;
DiskExtents := AllocMem(Max_Path);
if DeviceIoControl(hVolume, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, nil, 0, DiskExtents, Max_Path,
dwOutBytes, nil) then
begin
if DiskExtents^.NumberOfDiskExtents > 0 then
begin
DiskExtent := DiskExtents^.Extents[0];
Result := 0;
end
else
Result := -3;
end
else
Result := -2;
FreeMem(DiskExtents);
CloseHandle(hVolume);
end;