全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:3913
推到 Plurk!
推到 Facebook!

關於DeviceIoControl的使用

答題得分者是:hagar
mihopaul
一般會員


發表:25
回覆:59
積分:16
註冊:2002-03-17

發送簡訊給我
#1 引用回覆 回覆 發表時間:2002-09-12 09:54:20 IP:61.30.xxx.xxx 未訂閱
請教各位大大, 在delphi中,如果我要用這個api來驅動裝置的某一項功能該如何做呢?? 因為不知道該引入那些檔,又該做什麼處理,所以請教有經驗的各位大大 謝謝。
hagar
版主


發表:143
回覆:4056
積分:4445
註冊:2002-04-14

發送簡訊給我
#2 引用回覆 回覆 發表時間:2002-09-13 07:21:00 IP:211.22.xxx.xxx 未訂閱
一個範例, 取得 IDE 硬碟序號:
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. 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 
  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_CONTROL)); 
      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 := @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(sSerialNumber)); 
  end; 
end; 
hagar
版主


發表:143
回覆:4056
積分:4445
註冊:2002-04-14

發送簡訊給我
#3 引用回覆 回覆 發表時間:2002-09-13 07:32:28 IP:211.22.xxx.xxx 未訂閱
範例二: Question: Controlling my CD-ROM driver From: ZifNab  Date: 09/07/1999 02:23PM PST  
unit Unit1;    interface    uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, 
  Forms, Dialogs, StdCtrls, winioctl;    type
 TForm1 = class(TForm)
   Button1: TButton;
   Button2: TButton;
   Button3: TButton;
   procedure Button1Click(Sender: TObject);
   procedure Button2Click(Sender: TObject);
   procedure Button3Click(Sender: TObject);
   procedure CloseDevice;
   function Lock:boolean;
   function UnLock:boolean;
   function Eject:Boolean;
 private
   { Private declarations }
 public
   { Public declarations }
   reg: DEVIOCTL_REGISTERS;
   hDevice: THandle;
   cb: DWORD;
   lpFileName: PChar;
   pb: packed record
     operation, NumLocks: BYTE;
   end;
 end;    const    Drive = 'G';    var
  Form1: TForm1;    implementation    {$R *.DFM}    procedure TForm1.Button1Click(Sender: TObject);
begin
  if Eject then showmessage('Ok');
end;    procedure TForm1.Button2Click(Sender: TObject);
begin
  if Lock then showmessage('ok');
end;    procedure TForm1.Button3Click(Sender: TObject);
begin
  if UnLock then showmessage('ok');
end;    procedure TForm1.CloseDevice;
begin
  CloseHandle(hDevice);
end;    function TForm1.Lock;
begin
  if Win32Platform = VER_PLATFORM_WIN32_WINDOWS then
  begin
    reg.reg_EAX := $440D;  //* IOCTL for block devices */
    reg.reg_EBX := Ord(UpCase(Drive))-Ord ('A') 1; // zero-based drive ID
    reg.reg_ECX := MakeWOrd($48,8);
    reg.reg_EDX := DWORD(@pb);
    pb.operation := 0;
    if (not Win95IOCTL(@reg)) then
    begin
      result := FALSE;
      exit;
    end;        if (reg.reg_Flags and $0001) <> 0 then //* error if carry flag set
    begin
      result := FALSE;
      exit;
    end;
    Result := True;
  end
  // Windows NT (4.0 SP3) testing and corrections by Pawel Michalowski
  else if Win32Platform = VER_PLATFORM_WIN32_NT then
  begin
    // Using a variable assignment with lpFileName allows you to debug the
    // value you passed as 'Drive'.  Usually due to optimization this value
    // would be inaccessible. (PM)        lpFileName := PChar('\\.\' UpperCase(Drive) ':');
    // When getting the device handle in a call to CreateFile you have to
    // use GENERIC_READ (0 won't work) and FILE_ATTRIBUTE_NORMAL (again 0
    // won't work) (PM)        hDevice := CreateFile(lpFileName,
         GENERIC_READ{0}, FILE_SHARE_READ or FILE_SHARE_WRITE,
         nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL{0}, 0);        if hDevice = INVALID_HANDLE_VALUE{0} then
    begin
      Result := False;
      showmessage('error hdevice');
      Exit;
    end;
    Result := DeviceIoControl(hDevice, FSCTL_LOCK_VOLUME, nil, 0, nil, 0,cb, nil);
    CloseHandle(hDevice);
  end;
end;    function TForm1.UnLock;
begin
  if Win32Platform = VER_PLATFORM_WIN32_WINDOWS then
  begin
    reg.reg_EAX := $440D; //* IOCTL for block devices
    reg.reg_EBX := Ord(UpCase(Drive))-Ord ('A') 1; // zero-based drive ID
    reg.reg_ECX := MakeWOrd($48,8);
    reg.reg_EDX := DWORD(@pb);
    pb.operation := 1;
    if (not Win95IOCTL(@reg)) then
    begin
      result := FALSE;
      exit;
    end;        if (reg.reg_Flags and $0001) <> 0 then //* error if carry flag set 
    begin
      result := FALSE;
      exit;
    end;
    Result := True;
  end
  // Windows NT (4.0 SP3) testing and corrections by Pawel Michalowski
  else if Win32Platform = VER_PLATFORM_WIN32_NT then
  begin
    // Using a variable assignment with lpFileName allows you to debug the
    // value you passed as 'Drive'.  Usually due to optimization this value
    // would be inaccessible. (PM)        lpFileName := PChar('\\.\' UpperCase(Drive) ':');        // When getting the device handle in a call to CreateFile you have to
    // use GENERIC_READ (0 won't work) and FILE_ATTRIBUTE_NORMAL (again 0
    // won't work) (PM)        hDevice := CreateFile(lpFileName,
         GENERIC_READ{0}, FILE_SHARE_READ or FILE_SHARE_WRITE,
         nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL{0}, 0);        if hDevice = INVALID_HANDLE_VALUE{0} then
    begin
      Result := False;
      showmessage('error hdevice');
      Exit;
    end;
    Result := DeviceIoControl(hDevice,
         FSCTL_UNLOCK_VOLUME, nil, 0, nil, 0,cb, nil);
         CloseHandle(hDevice);
  end;
end;    function TForm1.Eject;
begin
  if Win32Platform = VER_PLATFORM_WIN32_WINDOWS then
  begin
    reg.reg_EAX := $440D; //* IOCTL for block devices
    reg.reg_EBX := Ord(UpCase(Drive))-Ord ('A') 1; // zero-based drive ID
    reg.reg_ECX := MakeWOrd($49,8);        if (not Win95IOCTL(@reg)) then
    begin
      result := FALSE;
      exit;
    end;        if (reg.reg_Flags and $0001) <> 0 then //* error if carry flag set
    begin
      result := FALSE;
      exit;
    end;
    Result := True;
  end
  // Windows NT (4.0 SP3) testing and corrections by Pawel Michalowski
  else if Win32Platform = VER_PLATFORM_WIN32_NT then
  begin
    // Using a variable assignment with lpFileName allows you to debug the
    // value you passed as 'Drive'.  Usually due to optimization this value
    // would be inaccessible. (PM)        lpFileName := PChar('\\.\' UpperCase(Drive) ':');        // When getting the device handle in a call to CreateFile you have to
    // use GENERIC_READ (0 won't work) and FILE_ATTRIBUTE_NORMAL (again 0
    // won't work) (PM)        hDevice := CreateFile(lpFileName,
    GENERIC_READ{0}, FILE_SHARE_READ or FILE_SHARE_WRITE,
         nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL{0}, 0);        if hDevice = INVALID_HANDLE_VALUE{0} then
    begin
      Result := False;
      Exit;
    end;
    Result := DeviceIoControl(hDevice,
         IOCTL_DISK_EJECT_MEDIA , nil, 0,
         nil,0, cb, nil);        CloseHandle(hDevice);
  end;
end;    end.
mihopaul
一般會員


發表:25
回覆:59
積分:16
註冊:2002-03-17

發送簡訊給我
#4 引用回覆 回覆 發表時間:2002-09-13 12:05:41 IP:61.30.xxx.xxx 未訂閱
不好意思,再請教一下,因為還有個重點 IOCTL命令的定義是用c語言來做的,所以 #define IOCTL_MY CTL_CODE(FILE_DEVICE_MY , \ 0X805,\ METHOD_BUFFERED, \ FILE_ANY_ACCESS) 這個要如何轉到delphi呢?? 不然在用該api時,不是會出錯嗎?? 還是範例引入的東東已有了呢?? 謝謝
系統時間:2024-04-26 1:25:15
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!