zoukankan      html  css  js  c++  java
  • XE 获取硬盘序列号

    function TdmCommonFun.GetIdeSerialNumber: AnsiString; stdcall;
    const
      IDENTIFY_BUFFER_SIZE = 512;
    type
      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;

      TSendCmdInParams = packed record
        // Buffer size in bytes
        cBufferSize: DWORD;
        // Structure with drive register values.
        irDriveRegs: TIDERegs;
        // Physical drive number to send command to (0,1,2,3).
        bDriveNumber: Byte;
        bReserved: array [0 .. 2] of Byte;
        dwReserved: array [0 .. 3] of DWORD;
        bBuffer: array [0 .. 0] of Byte; // Input buffer.
      end;

      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 ansiCHAR;
        wBufferType: word;
        wBufferSize: word;
        wECCSize: word;
        sFirmwareRev: array [0 .. 7] of ansiCHAR;
        sModelNumber: array [0 .. 39] of ansiCHAR;
        wMoreVendorUnique: word;
        wDoubleWordIO: word;
        wCapabilities: word;
        wReserved1: word;
        wPIOTiming: word;
        wDMATiming: word;
        wBS: word;
        wNumCurrentCyls: word;
        wNumCurrentHeads: word;
        wNumCurrentSectorsPerTrack: word;
        ulCurrentSectorCapacity: DWORD;
        wMultSectorStuff: word;
        ulTotalAddressableSectors: DWORD;
        wSingleWordDMA: word;
        wMultiWordDMA: word;
        bReserved: array [0 .. 127] of Byte;
      end;

      PIdSector = ^TIdSector;

      TDriverStatus = packed record
        // 驱动器返回的错误代码,无错则返回0
        bDriverError: Byte;
        // IDE出错寄存器的内容,只有当bDriverError 为 SMART_IDE_ERROR 时有效
        bIDEStatus: Byte;
        bReserved: array [0 .. 1] of Byte;
        dwReserved: array [0 .. 1] of DWORD;
      end;

      TSendCmdOutParams = packed record
        // bBuffer的大小
        cBufferSize: DWORD;
        // 驱动器状态
        DriverStatus: TDriverStatus;
        // 用于保存从驱动器读出的数据的缓冲区,实际长度由cBufferSize决定
        bBuffer: array [0 .. 0] of Byte;
      end;
    var
      hDevice: THandle;
      cbBytesReturned: DWORD;
      SCIP: TSendCmdInParams;
      aIdOutCmd: array [0 .. (SizeOf(TSendCmdOutParams) + IDENTIFY_BUFFER_SIZE - 1)
        - 1] of Byte;
      IdOutCmd: TSendCmdOutParams absolute aIdOutCmd;

      procedure ChangeByteOrder(var Data; Size: Integer);
      var
        ptr: PansiChar;
        i: Integer;
        c: ansiCHAR;
      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 := ''; // 如果出错则返回空串

      if SysUtils.Win32Platform = VER_PLATFORM_WIN32_NT then
      // Windows NT, Windows 2000
      begin
        // 提示! 改变名称可适用于其它驱动器,如第二个驱动器: '\\.\PhysicalDrive1\'
        hDevice := CreateFile('\\.\PhysicalDrive0', GENERIC_READ or GENERIC_WRITE,
          FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
      end
      else // Version Windows 95 OSR2, Windows 98
        hDevice := CreateFile('\\.\SMARTVSD', 0, 0, nil, CREATE_NEW, 0, 0);

      if hDevice = INVALID_HANDLE_VALUE then
        Exit;

      try
        FillChar(SCIP, SizeOf(TSendCmdInParams) - 1, #0);
        FillChar(aIdOutCmd, SizeOf(aIdOutCmd), #0);
        cbBytesReturned := 0;

        // Set up data structures for IDENTIFY command.
        with SCIP do
        begin
          cBufferSize := IDENTIFY_BUFFER_SIZE;

          // bDriveNumber := 0;
          with irDriveRegs do
          begin
            bSectorCountReg := 1;
            bSectorNumberReg := 1;

            // if Win32Platform=VER_PLATFORM_WIN32_NT then bDriveHeadReg := $A0
            // else bDriveHeadReg := $A0 or ((bDriveNum and 1) shl 4);
            bDriveHeadReg := $A0;
            bCommandReg := $EC;
          end;
        end;

        if not DeviceIoControl(hDevice, $0007C088, @SCIP, SizeOf(TSendCmdInParams) -
          1, @aIdOutCmd, SizeOf(aIdOutCmd), cbBytesReturned, nil) then
          Exit;
      finally
        CloseHandle(hDevice);
      end;

      with PIdSector(@IdOutCmd.bBuffer)^ do
      begin
        ChangeByteOrder(sSerialNumber, SizeOf(sSerialNumber));
        (PansiChar(@sSerialNumber) + SizeOf(sSerialNumber))^ := #0;

        Result := trim(StrPas(PansiChar(@sSerialNumber)));

      end;
    end;

  • 相关阅读:
    洛谷 P2234 [HNOI2002]营业额统计
    洛谷p3146&p3147
    洛谷 p1439 最长公共子序列
    搜索
    一步一步分析Caliburn.Micro(二:绑定执行方法Message现学现卖之自定命令)
    一步一步分析Caliburn.Micro(一:绑定执行方法Message)
    整理的C# 字符串类
    不用ADOX.CatalogClass创建Access数据库文件
    取远程网页数据 WebClient,HttpWebRequest
    C# LinQ 与 ADO.NET
  • 原文地址:https://www.cnblogs.com/hnxxcxg/p/2846409.html
Copyright © 2011-2022 走看看