在DEPHI中如何读取硬盘的序列号

解决方案 »

  1.   


    function GetHDSerialNo: string;
    {
      返回第一个硬盘的硬盘硬件序列号  IDE Primary master时,  文件名为Scsi0,bDriveNumber为0
      IDE Primary slave 时,  文件名为Scsi0,bDriveNumber为1
      IDE Secondary master时,文件名为Scsi1,bDriveNumber为0
      IDE Secondary slave 时,文件名为Scsi1,bDriveNumber为1
    }
    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. Must be 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;
    var
      hDevice: THandle;
      cbBytesReturned: DWORD;
      pInData: PSendCmdInParams;
      pOutData: Pointer; // PSendCmdOutParams
      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
      FillChar(Buffer, BufferSize, #0);
      if Win32Platform = VER_PLATFORM_WIN32_NT then
      begin
        with srbControl do
        begin
          Move('SCSIDISK', Signature, 8);
          Timeout := 2;
          Length := DataSize;
          ControlCode := IOCTL_SCSI_MINIPORT_IDENTIFY;
          HeaderLength := SizeOf(SRB_IO_CONTROL);
        end;    pInData := PSendCmdInParams(PChar(@Buffer) + SizeOf(SRB_IO_CONTROL));
        pOutData := pInData;
        hDevice := CreateFile('\\.\PHYSICALDRIVE0', GENERIC_READ or GENERIC_WRITE,
          FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
      end
      else
      begin
        pInData := PSendCmdInParams(@Buffer);
        pOutData := @pInData^.bBuffer;
        hDevice := CreateFile('\\.\SMARTVSD', 0, 0, nil, CREATE_NEW, 0, 0);
      end;
      if hDevice = INVALID_HANDLE_VALUE then Exit;  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 Win32Platform = VER_PLATFORM_WIN32_NT then
        DeviceIoControl(hDevice, IOCTL_SCSI_MINIPORT, @Buffer, BufferSize, @Buffer, BufferSize,
          cbBytesReturned, nil)
      else // Windows 95 OSR2, Windows 98
        DeviceIoControl(hDevice, DFP_RECEIVE_DRIVE_DATA, pInData, SizeOf(TSendCmdInParams) - 1, pOutData,
          W9xBufferSize, cbBytesReturned, nil);
      CloseHandle(hDevice);
      with PIdSector(PChar(pOutData) + 16)^ do
      begin
        ChangeByteOrder(sSerialNumber, SizeOf(sSerialNumber));
        Result := sSerialNumber;
      end;
    end;你直接调用就可以获得硬盘号了
      

  2.   

    不过不支持SATA的
    SATA要用MiniPort方法的
      

  3.   


    var 
      SerialNum : pdword;
      a,b : dword;
      Buffer : array [0..255] of char; 
    begin 
      if GetVolumeInformation(‘c:\‘, Buffer, SizeOf(Buffer), SerialNum, a, b, nil, 0) then 
          Label1.Caption := IntToStr(SerialNum^); 
    end;