Конференция "WinAPI" » Серийный номер Диска (не Тома) [D7, WinXP]
 
  • Delins (07.10.09 11:41) [0]
    Везде говорится что при помощи функции GetVolumeInformation можно узнать уникальный номер винта (флешки)
    Но у меня возвращается одно и то же значение для разных флешек.
    Задача моей программы:
    1. Определить момент когда подключается флешка; Определяю с помощью следующей процедуры:
    Procedure WMDeviceChange(var Msg: TMessage); message WM_DeviceChange;


    Пример можно найти в инете
    2. Определить уникальный номер флешки.
    Делаю так:

    Buffer := '';
    SerialNum := 0;
    GetVolumeInformation(PChar(Drive),Buffer,sizeof(Buffer),@SerialNum,a,b,nil,0);
    Label1.Caption := Drive+' - '+SerialNum;


    Вынимаю флешку, вставляю другую, номер не меняется.

    Пробовал использовать функцию GetFileInformationByHandle

           hDir := CreateFile(PChar(Drive),GENERIC_WRITE,FILE_SHARE_DELETE,nil,OPEN_EXISTING,FILE_A TTRIBUTE_DIRECTORY,FILE_FLAG_WRITE_THROUGH);
           GetFileInformationByHandle(hDir, Info);
           Label1.Caption := VarToStr(Info.dwVolumeSerialNumber);


    В разных портах выдает различное значение, а для разных флешек, в одном порту одинаковое...
    Подскажите пожалуйста, есть ли возможность узнать реальный номер флешки?
  • KilkennyCat © (07.10.09 12:02) [1]
    >> Поличение серийного номера IDE диска.  Функция
    получает серийный номер первого физического диска IDE
    (не серийный номер тома!). Используется S.M.A.R.T. API, а
    под Windows NT/2K/XP запрос производится не напрямую к
    диску, а через miniport драйвер контроллера, что позволяет читать серийный номер не имея прав
    администратора. Функция может не работать, если первый
    контролер в системе не ATA или если первое устройство не
    является винчестером, который поддерживает SMART
    (современные винчестеры поддерживают). Если Вы хотите
    получить другие параметры диска/других дисков, то
    смотрите пример IdeInfo2 с моего сайта. На Windows 9x
    требует наличия драйвера smartvsd.vxd (должен быть в
    стандартной поставке), просто скопируйте его в \windows
    \system\iosubsys и перезагрузите компьютер.  Зависимости:
    Windows, SysUtils Автор: Alex Konshin,
    akonshin@earthlink.net, Boston, USA Copyright:
    http://home.earthlink.net/~akonshin/index.htm Дата: 30
    декабря 2002 г.
    **************************************************  *** }  

    function GetIdeDiskSerialNumber : 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;
    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
    // Get SCSI port handle
    hDevice := CreateFile( '\\.\Scsi0:', 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_CONT   ROL));
    pOutData := pInData;
    with pInData^ do
    begin
    cBufferSize := IDENTIFY_BUFFER_SIZE;
    bDriveNumber := 0; 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
    hDevice := CreateFile( '\\.\SMARTVSD', 0, 0, nil, CREATE_NEW, 0, 0 );
    if hDevice=INVALID_HANDLE_VALUE then Exit;
    try
    pInData := PSendCmdInParams(@Buffer);
    pOutData := PChar(@pInData^.bBuffer);
    with pInData^ do
    begin
    cBufferSize := IDENTIFY_BUFFER_SIZE;
    bDriveNumber := 0;
    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(sSerialNumbe   r));
    end;
    end;

    Пример использования:  
    var s : String; rc : DWORD;
    begin
    s := GetIdeDiskSerialNumber;
    if s='' then
    begin
    rc := GetLastError;
    if rc=0 then
    WriteLn('IDE drive is not support SMART feature')
    else
    WriteLn(SysErrorMessage(rc)); end else WriteLn('Disk serial number: ''', s,'''');
    end.  

    Автор: Alex Konshin
  • Delins (07.10.09 14:04) [2]
    Спасибо большое за информацию...
    Но данный пример работает только для винчестеров.
  • Delins (07.10.09 15:25) [3]
    Тему можно закрыть. Ответ нашел тут:
    http://www.ureader.com/message/1018345.aspx
 
Конференция "WinAPI" » Серийный номер Диска (не Тома) [D7, WinXP]
Есть новые Нет новых   [134433   +21][b:0][p:0.001]