详细如下:
type
      _STORAGE_DEVICE_DESCRIPTOR   =   record
          Version:   LongInt;   //   版本
          Size:   LongInt;   //   结构大小
          DeviceType:   Char;   //   设备类型
          DeviceTypeModifier:   Char;   //   SCSI-2额外的设备类型
          RemovableMedia:   BOOLEAN;   //   是否可移动
          CommandQueueing:   BOOLEAN;   //   是否支持命令队列
          VendorIdOffset:   LongInt;   //   厂家设定值的偏移
          ProductIdOffset:   LongInt;   //   产品ID的偏移
          ProductRevisionOffset:   LongInt;   //   产品版本的偏移
          SerialNumberOffset:   LongInt;   //   序列号的偏移
          BusType:   STORAGE_BUS_TYPE;   //   总线类型
          RawPropertiesLength:   longInt;   //   额外的属性数据长度
          RawDeviceProperties:   array[1..1]   of   Char;   //   额外的属性数据(仅定义了象征性的1个字节)
      end;
      STORAGE_DEVICE_DESCRIPTOR   =   _STORAGE_DEVICE_DESCRIPTOR;
      PSTORAGE_DEVICE_DESCRIPTOR   =   ^STORAGE_DEVICE_DESCRIPTOR;
 pDevDesc:   PSTORAGE_DEVICE_DESCRIPTOR;          DeviceIoControl(hDevice,   //   设备句柄
          IOCTL_STORAGE_QUERY_PROPERTY,   //   取设备属性信息
          @Query,   sizeof(STORAGE_PROPERTY_QUERY),   //   输入数据缓冲区
          pDevDesc,   pDevDesc.Size,   //   输出数据缓冲区
          dwOutBytes,   //   输出数据长度
          nil);
上面的代码读取了STORAGE_DEVICE_DESCRIPTOR,也可取得该结构中的DeviceType值,我想问如何取得其serialnumber,因为
该结构中定义的是serialnumberoffset。谢谢

解决方案 »

  1.   

    type
      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;
      IDEREGS = 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;
      SENDCMDINPARAMS = record
          cBufferSize :DWORD;
          irDriveRegs :IDEREGS;
          bDriveNumber:BYTE;
          bReserved   :Array[0..2] of BYTE;
          dwReserved  :Array[0..3] of DWORD;
          bBuffer     :BYTE;
      end;
      DRIVERSTATUS = record
          bDriverError:BYTE;
          bIDEStatus  :BYTE;
          bReserved   :Array[0..1] of BYTE;
          dwReserved  :Array[0..1] of DWORD;
      end;
      SENDCMDOUTPARAMS = record
          cBufferSize :DWORD;
          DriverStatus:DRIVERSTATUS;
          bBuffer     :BYTE;
      end;
      PSENDCMDOUTPARAMS = ^SENDCMDOUTPARAMS;
      // ·ÖÇøÀ©Õ¹ÐÅÏ¢
      TDiskExtent = record
        DiskNumber: Cardinal;
        StartingOffset: LARGE_INTEGER;
        ExtentLength: LARGE_INTEGER;
      end;
      DISK_EXTENT = TDiskExtent;
      PDiskExtent = ^TDiskExtent;  TVolumeDiskExtents = record
        NumberOfDiskExtents: Cardinal;
        Extents: array [0..0] of TDiskExtent;
      end;
      VOLUME_DISK_EXTENTS = TVolumeDiskExtents;
      PVolumeDiskExtents = ^TVolumeDiskExtents;
    function GetDiskInformation(byNumber: BYTE):String;
    function GetVolumeInfo(DriverLetter: Char; var DiskExtent: TDiskExtent): Integer;implementationprocedure 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;
    function GetDiskInformation(byNumber: BYTE): String;
    var
        hDevice:THandle;
        cbBytesReturned:Dword;
        s :String;
        scip    :SENDCMDINPARAMS;
    OutCmd  :SENDCMDOUTPARAMS;
        IdOutCmd:Array[0..sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1] of BYTE;begin
        result:='';
        if Win32Platform=VER_PLATFORM_WIN32_NT then
        begin// Windows NT, Windows 2000
            // Get SCSI port handle
            hDevice:=CreateFile(PChar('\\.\PhysicalDrive'+Inttostr(byNumber)),
                GENERIC_READ or GENERIC_WRITE,
                FILE_SHARE_READ or FILE_SHARE_WRITE,
                nil,
                OPEN_EXISTING,
                0,
                0);
        end
        else
          hDevice:=CreateFile('\\.\SMARTVSD',0,0,nil,CREATE_NEW,0,0);    if hDevice=INVALID_HANDLE_VALUE then
            Exit;
        FillChar(scip, 0, sizeof(scip));
        FillChar(OutCmd, 0, sizeof(OutCmd));
        scip.cBufferSize := IDENTIFY_BUFFER_SIZE;
        scip.irDriveRegs.bFeaturesReg := 0;
        scip.irDriveRegs.bSectorCountReg := 1;
        scip.irDriveRegs.bSectorNumberReg := 1;
        scip.irDriveRegs.bCylLowReg := 0;
        scip.irDriveRegs.bCylHighReg := 0;    scip.irDriveRegs.bDriveHeadReg := $A0;// | ((bDriveNum & 1) << 4);    scip.irDriveRegs.bCommandReg := IDE_ID_FUNCTION;
        scip.bDriveNumber := 0;//bDriveNum;
        scip.cBufferSize := IDENTIFY_BUFFER_SIZE;    try
          if not DeviceIoControl(hDevice,
            DFP_RECEIVE_DRIVE_DATA,
            @scip, sizeof(SENDCMDINPARAMS) - 1,
            @IdOutCmd, sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
            cbBytesReturned,nil) then Exit;    finally
            CloseHandle(hDevice);
        end;
        with PIdSector(@PSENDCMDOUTPARAMS(@IdOutCmd[0]).bBuffer)^ do
        begin
          ChangeByteOrder(sModelNumber, sizeof(sModelNumber));
          ChangeByteOrder(sSerialNumber,SizeOf(sSerialNumber));      ChangeByteOrder(sFirmwareRev, sizeof(sFirmwareRev));      SetString(result,sModelNumber,SizeOf(sModelNumber));
          SetString(s,sSerialNumber,SizeOf(sSerialNumber));
          Result := Trim(Result)+'|'+Trim(s)+'|'+Trim(sFirmwareRev);
        end;
    end;
    function GetVolumeInfo(DriverLetter: Char; var DiskExtent: TDiskExtent): Integer;
    var
        hVolume: THandle;
        DiskExtents: PVolumeDiskExtents;
        dwOutBytes: Cardinal;
    begin
        Result := -1;
        hVolume := CreateFile(PChar('\\.\'+DriverLetter+':'), GENERIC_READ or GENERIC_WRITE,
            FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
        if hVolume < 1 then
            Exit;
        DiskExtents := AllocMem(Max_Path);
        if DeviceIoControl(hVolume, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, nil, 0, DiskExtents, Max_Path,
            dwOutBytes, nil) then
        begin
            if DiskExtents^.NumberOfDiskExtents > 0 then
            begin
                DiskExtent := DiskExtents^.Extents[0];
                Result := 0;
            end
            else
                Result := -3;
        end
        else
            Result := -2;
        FreeMem(DiskExtents);
        CloseHandle(hVolume);
    end;