關於DeviceIoControl的使用 |
答題得分者是:hagar
|
mihopaul
一般會員 發表:25 回覆:59 積分:16 註冊:2002-03-17 發送簡訊給我 |
|
hagar
版主 發表:143 回覆:4056 積分:4445 註冊:2002-04-14 發送簡訊給我 |
一個範例, 取得 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 發送簡訊給我 |
範例二:
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 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |