Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
Gente sei que ja existe topico sobre esse assunto peguei o codigo e ja testei em 03 versões do delphi mais não funciona em nenhuma, algum pode me ajudar?
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
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; pc:=@Data;
for i:=0 to (Size shr 1)-1 do begin
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;
const
IDE_ID_FUNCTION=$EC;
IDENTIFY_BUFFER_SIZE=512;
DFP_RECEIVE_DRIVE_DATA=$0007c088;
IOCTL_SCSI_MINIPORT=$0004d008;
IOCTL_SCSI_MINIPORT_IDENTIFY=$001b0501;
DataSize=sizeof(TSendCmdInParams)-1+IDENTIFY_BUFFER_SIZE;
BufferSize=SizeOf(SRB_IO_CONTROL)+DataSize;
W9xBufferSize=IDENTIFY_BUFFER_SIZE+16; hDevice:THandle;
cbBytesReturned:DWORD;
pInData:PSendCmdInParams;
pOutData:Pointer; // PSendCmdOutParams
Buffer:Array[0..BufferSize-1]of Byte;
srbControl:TSrbIoControl absolute Buffer;
begin
Result:='';
FillChar(Buffer,BufferSize,#0);
// Windows NT, Windows 2000, Windows XP
if Win32Platform=VER_PLATFORM_WIN32_NT then begin
// 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^ do begin
cBufferSize:=IDENTIFY_BUFFER_SIZE;
bDriveNumber:=nPos; {Observar aqui! posição mestre ou escravo }
with irDriveRegs do begin
bFeaturesReg:=0;
bSectorCountReg:=1;
bSectorNumberReg:=1;
bCylLowReg:=0;
bCylHighReg:=0;
bDriveHeadReg:=$A0;
bCommandReg:=IDE_ID_FUNCTION;
end;
end;
if not DeviceIoControl(hDevice,IOCTL_SCSI_MINIPORT,@Buffer,
BufferSize,@Buffer,BufferSize,cbBytesReturned,nil)then Exit;
finally CloseHandle(hDevice); end;
end
else begin
// 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^ do begin
cBufferSize:=IDENTIFY_BUFFER_SIZE;
bDriveNumber:=nPos; {Observar aqui! posição mestre ou escravo }
with irDriveRegs do begin
bFeaturesReg:=0;
bSectorCountReg:=1;
bSectorNumberReg:=1;
bCylLowReg:=0;
bCylHighReg:=0;
bDriveHeadReg:=$A0;
bCommandReg:=IDE_ID_FUNCTION;
end;
end;
if not 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)^ do begin
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; ListBox1.Clear;
for a:=0 to 5 do begin
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;
end.
>
Eu utilizo esta função:
Function SerialNum(FDrive:String) :String;
Var
Serial:DWord;
DirLen,Flags: DWord;
DLabel : Array[0..11] of Char; GetVolumeInformation(PChar(FDrive+’:\’),dLabel,12,@Serial,DirLen,Flags,nil,0);
Result := IntToHex(Serial,8);
Except
Result :='';
end;
end;
Tem funcionado bem.
:D
Desculpa a intromissão
Essa função pega o serial fisico do HD? Ou Seja, aquele que não se altera na formatação?
Funciona com todos HDs? (SataI, SataII, SataIII...)
Olha amigo, eu uso delphi 7 e aqui funciona a função a seguir:
function GetIdeDiskSerialNumber( ControllerNumber, DriveNumber : Integer ) : 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; // 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;
IDEREGS = TIDERegs;
PIDERegs = ^TIDERegs;
TSendCmdInParams = packed record
cBufferSize : DWORD; // Buffer size in bytes
irDriveRegs : TIDERegs; // Structure with drive register values.
bDriveNumber : Byte; // Physical drive number to send command to (0,1,2,3).
bReserved : Array[0..2] of Byte; // Reserved for future expansion.
dwReserved : Array[0..3] of DWORD; // For future use.
bBuffer : Array[0..0] of Byte; // Input buffer.
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;
const
IDE_ID_FUNCTION = $EC;
IDENTIFY_BUFFER_SIZE = 512;
DFP_RECEIVE_DRIVE_DATA = $0007c088;
IOCTL_SCSI_MINIPORT = $0004d008;
IOCTL_SCSI_MINIPORT_IDENTIFY = $001b0501;
DataSize = sizeof(TSendCmdInParams)-1+IDENTIFY_BUFFER_SIZE;
BufferSize = SizeOf(SRB_IO_CONTROL)+DataSize;
W9xBufferSize = IDENTIFY_BUFFER_SIZE+16;
var
hDevice : THandle;
cbBytesReturned : DWORD;
s : String;
pInData : PSendCmdInParams;
pOutData : Pointer; // PSendCmdInParams;
Buffer : Array[0..BufferSize-1] of Byte;
srbControl : TSrbIoControl absolute Buffer;
procedure 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;
begin
Result := '';
FillChar(Buffer,BufferSize,#0);
if Win32Platform=VER_PLATFORM_WIN32_NT then
begin // Windows NT, Windows 2000
Str(ControllerNumber,s);
// Get SCSI port handle
hDevice := CreateFile(
PChar('\\.\Scsi'+s+':'),
GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0 );
if hDevice=INVALID_HANDLE_VALUE then RaiseLastOSError;
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^ do
begin
cBufferSize := IDENTIFY_BUFFER_SIZE;
bDriveNumber := DriveNumber;
with irDriveRegs do
begin
bFeaturesReg := 0;
bSectorCountReg := 1;
bSectorNumberReg := 1;
bCylLowReg := 0;
bCylHighReg := 0;
bDriveHeadReg := $A0 or ((DriveNumber and 1) shl 4);
bCommandReg := IDE_ID_FUNCTION;
end;
end;
if not DeviceIoControl( hDevice, IOCTL_SCSI_MINIPORT, @Buffer, BufferSize, @Buffer, BufferSize, cbBytesReturned, nil ) then RaiseLastOSError;
finally
CloseHandle(hDevice);
end;
end
else
begin // Windows 95 OSR2, Windows 98
hDevice := CreateFile( '\\.\SMARTVSD', 0, 0, nil, CREATE_NEW, 0, 0 );
if hDevice=INVALID_HANDLE_VALUE then RaiseLastOSError;
try
pInData := PSendCmdInParams(@Buffer);
pOutData := PChar(@pInData^.bBuffer);
with pInData^ do
begin
cBufferSize := IDENTIFY_BUFFER_SIZE;
bDriveNumber := DriveNumber;
with irDriveRegs do
begin
bFeaturesReg := 0;
bSectorCountReg := 1;
bSectorNumberReg := 1;
bCylLowReg := 0;
bCylHighReg := 0;
bDriveHeadReg := $A0 or ((DriveNumber and 1) shl 4);
bCommandReg := IDE_ID_FUNCTION;
end;
end;
if not DeviceIoControl( hDevice, DFP_RECEIVE_DRIVE_DATA, pInData, SizeOf(TSendCmdInParams)-1, pOutData, W9xBufferSize, cbBytesReturned, nil ) then RaiseLastOSError;
finally
CloseHandle(hDevice);
end;
end;
with PIdSector(PChar(pOutData)+16)^ do
begin
ChangeByteOrder(sSerialNumber,SizeOf(sSerialNumber));
SetString(Result,sSerialNumber,SizeOf(sSerialNumber));
end;
Result := Trim(Result);
end;
function GetIdeSN : String;
var
iController, iDrive, maxController : Integer;
begin
Result := '';
maxController := 15;
if Win32Platform<>VER_PLATFORM_WIN32_NT then maxController := 0;
for iController := 0 to maxController do
begin
for iDrive := 0 to 4 do
begin
try
Result := GetIdeDiskSerialNumber(iController,iDrive);
if Result<>'' then Exit;
except
// ignore exceptions
end;
end;
end;
end;
Use assim:
procedure TForm1.BitBtn1Click(Sender: TObject);
var
s: string;
begin
s := GetIdeSN;
edit1.text := s;
end;
****
Espero ter ajudado! :)
Obs.: Pega o serial real(físico) do HD.
Muito obg pela ajuda mais ainda não funfou, ja testei no delphi 6 e no 2010 mais da alguns erros, mais valeu.
>
Desculpa a intromissão
Essa função pega o serial fisico do HD? Ou Seja, aquele que não se altera na formatação?
Funciona com todos HDs? (SataI, SataII, SataIII...)
Olha, agora que você perguntou eu fiquei com uma pulga atras da orelha. Mas acho que sim. Pior é que é complicado testar uma função dessas.. :(
^_^
:D
A função do Raficcha pega o serial logico o que muda toda vez que o HD é formatado, já a do Livio Bruno é para pegar o serial fisico.
Eu utilizo esta função:
Function SerialNum(FDrive:String) :String;
Var
begin
Try
Tem funcionado bem.
:D