{
A dica original eu peguei com vocês. Ela só lê o disco mestre.
Um dos nossos colegas não conseguiu ler o HD SATA,
acreditando assim que a função não funcionava para o SATA.
Provavelmente seu HD devia estar como escravo.
Acrescentei uma variavel para os escravos tambem.
Espero ter ajudado.
feraugrab (fernando).
} unit UDiskSerial;
type
TForm1 =class(TForm)
ListBox1: TListBox; procedure FormCreate(Sender: TObject); private { Private declarations } public { Public declarations } end;
var
Form1: TForm1;
implementation {$R *.DFM} procedure ChangeByteOrder( var Data; Size : Integer ); var
pc:PChar;
c:Char;
i:Integer; begin
pc:=@Data; for i:=0 to (Size shr 1)-1 dobegin
c:=pc^;
pc^:=(pc+1)^;
(pc+1)^:=c;
Inc(pc,2); end; end;
{ função que pega o serial number FÍSICO do HD e retorna string } function DadosDisco(nPort:string; nPos:Byte):String; type
TSrbIoControl=packed record
HeaderLength:ULONG;
Signature:Array[0..7]of Char;
Timeout:ULONG;
ControlCode:ULONG;
ReturnCode:ULONG;
Length:ULONG; end;
SRB_IO_CONTROL=TSrbIoControl;
PSrbIoControl=^TSrbIoControl;
TIDERegs=packed record
bFeaturesReg:Byte; // especificar "comandos" SMART
bSectorCountReg:Byte; // registro de contador de setor
bSectorNumberReg:Byte; // registro de número de setores
bCylLowReg:Byte; // valor de cilindro (byte mais baixo)
bCylHighReg:Byte; // valor de cilindro (byte mais alto)
bDriveHeadReg:Byte; // registro de drive/cabeça
bCommandReg:Byte; // comando IDE
bReserved:Byte; // reservado- tem que ser zero end;
IDEREGS=TIDERegs;
PIDERegs=^TIDERegs;
TSendCmdInParams=packed record
cBufferSize:DWORD;
irDriveRegs:TIDERegs;
bDriveNumber:Byte;
bReserved:Array[0..2]of Byte;
dwReserved:Array[0..3]of DWORD;
bBuffer:Array[0..0]of Byte; end;
SENDCMDINPARAMS=TSendCmdInParams;
PSendCmdInParams=^TSendCmdInParams;
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;
begin
Result:='';
FillChar(Buffer,BufferSize,#0); // Windows NT, Windows 2000, Windows XP if Win32Platform=VER_PLATFORM_WIN32_NT thenbegin // recuperar handle da porta SCSI {hDevice:=CreateFile('\.SCSI0:',} // Nota: '\.C:' precisa de privilégios administrativos
hDevice:=CreateFile(pchar('\.SCSI'+nPort+':'),
GENERIC_READ or GENERIC_WRITE,FILE_SHARE_READ or FILE_SHARE_WRITE, nil,OPEN_EXISTING,0,0); if hDevice=INVALID_HANDLE_VALUE then Exit; try
srbControl.HeaderLength:=SizeOf(SRB_IO_CONTROL);
System.Move('SCSIDISK',srbControl.Signature,8);
srbControl.Timeout:=2;
srbControl.Length:=DataSize;
srbControl.ControlCode:=IOCTL_SCSI_MINIPORT_IDENTIFY;
pInData:=PSendCmdInParams(PChar(@Buffer)+SizeOf(SRB_IO_CONTROL));
pOutData:=pInData; with pInData^ dobegin
cBufferSize:=IDENTIFY_BUFFER_SIZE;
bDriveNumber:=nPos; {Observar aqui! posição mestre ou escravo } with irDriveRegs dobegin
bFeaturesReg:=0;
bSectorCountReg:=1;
bSectorNumberReg:=1;
bCylLowReg:=0;
bCylHighReg:=0;
bDriveHeadReg:=$A0;
bCommandReg:=IDE_ID_FUNCTION; end; end; ifnot DeviceIoControl(hDevice,IOCTL_SCSI_MINIPORT,@Buffer,
BufferSize,@Buffer,BufferSize,cbBytesReturned,nil)then Exit; finally CloseHandle(hDevice); end; end elsebegin // Windows 95 OSR2, Windows 98, Windows ME
hDevice:=CreateFile( '\.SMARTVSD',0,0, nil,CREATE_NEW,0,0 ); if hDevice=INVALID_HANDLE_VALUE then Exit; try
pInData:=PSendCmdInParams(@Buffer);
pOutData:=@pInData^.bBuffer; with pInData^ dobegin
cBufferSize:=IDENTIFY_BUFFER_SIZE;
bDriveNumber:=nPos; {Observar aqui! posição mestre ou escravo } with irDriveRegs dobegin
bFeaturesReg:=0;
bSectorCountReg:=1;
bSectorNumberReg:=1;
bCylLowReg:=0;
bCylHighReg:=0;
bDriveHeadReg:=$A0;
bCommandReg:=IDE_ID_FUNCTION; end; end; ifnot DeviceIoControl(hDevice,DFP_RECEIVE_DRIVE_DATA,pInData,
SizeOf(TSendCmdInParams)-1,pOutData,W9xBufferSize,cbBytesReturned,nil)then Exit; finally CloseHandle(hDevice); end; end; {with PIdSector(PChar(pOutData)+16)^ do begin
ChangeByteOrder(sSerialNumber,SizeOf(sSerialNumber));
SetString(Result,sSerialNumber,SizeOf(sSerialNumber));
end;} with PIdSector(PChar(pOutData)+16)^ dobegin
ChangeByteOrder(sModelNumber,SizeOf(sModelNumber));
Result:=Trim(sModelNumber);
ChangeByteOrder(sSerialNumber,SizeOf(sSerialNumber));
Result:=Result+'/'+Trim(sSerialNumber);
ChangeByteOrder(sFirmwareRev,SizeOf(sFirmwareRev));
Result:=Result+'/'+Trim(sFirmwareRev); end; end;
procedure TForm1.FormCreate(Sender: TObject); var a:Integer; begin
ListBox1.Clear; for a:=0 to 5 dobegin
ListBox1.Items.Add('Posição: '+IntToStr(a));
ListBox1.Items.Add(' Mestre: '+Trim(DadosDisco(IntToStr(a),0)));
ListBox1.Items.Add(' Escravo: '+Trim(DadosDisco(IntToStr(a),1)));
ListBox1.Items.Add(''); end; end;