天天看點

DeviceIoControl詳解

DeviceIoControl的使用說明

應用程式和驅動程式的通信過程是:應用程式使用CreateFile函數打開裝置,然後用DeviceIoControl與驅動程式進行通信,包括讀和寫兩種操作。還可以用ReadFile讀資料用WriteFile寫資料。操作完畢時用CloseHandle關閉裝置。我們比較常用的就是用DeviceIoControl對裝置進行讀寫操作。先看看DeviceIoControl是怎麼定義的:

BOOL DeviceIoControl(

  HANDLE hDevice,

  DWORD dwIoControlCode,

  LPVOID lpInBuffer,

  DWORD nInBufferSize,

  LPVOID lpOutBuffer,

  DWORD nOutBufferSize,

  LPDWORD lpBytesReturned,

  LPOVERLAPPED lpOverlapped

);Parameters(參數)

hDevice (CreateFile傳回的裝置句柄)

[in] Handle to the device that is to perform the operation. To obtain a device handle, call the CreateFile function.

dwIoControlCode (應用程式調用驅動程式的控制指令,就是IOCTL_XXX IOCTLs )

[in] IOCTL for the operation. This value identifies the specific operation to perform and the type of device on which to perform the operation. There are no specific values defined for the dwIoControlCode parameter. However, you can define custom IOCTL_XXX IOCTLs with the CTL_CODE macro. You can then advertise these IOCTLs and an application can use these IOCTLs with DeviceIoControl to perform the driver-specific functions.

lpInBuffer (應用程式傳遞給驅動程式的資料緩沖區位址)

[in] Long pointer to a buffer that contains the data required to perform the operation. Set to NULL if the dwIoControlCode parameter specifies an operation that does not require input data.

nInBufferSize (應用程式傳遞給驅動程式的資料緩沖區大小,位元組數)

[in] Size, in bytes, of the buffer pointed to by lpInBuffer.

lpOutBuffer (驅動程式傳回給應用程式的資料緩沖區位址)

[out] Long pointer to a buffer that receives the output data for the operation. Set to NULL if the dwIoControlCode parameter specifies an operation that does not produce output data.

nOutBufferSize (驅動程式傳回給應用程式的資料緩沖區大小,位元組數)

[out] Size, in bytes, of the buffer pointed to by lpOutBuffer.

lpBytesReturned (驅動程式實際傳回給應用程式的資料位元組數位址)

[out] Long pointer to a variable that receives the size, in bytes, of the data stored in lpOutBuffer. The DeviceIoControl function may unnecessarily use this parameter. For example, if an operation does not produce data for lpOutBuffer and lpOutBuffer is NULL, the value of lpBytesReturned is meaningless.

lpOverlapped (重疊操作結構)

[in] Ignored; set to NULL.

Return Values(傳回值)

Nonzero indicates success. Zero indicates failure. To obtain extended error information, call the GetLastError function. (非0成功,0失敗)

具體使用我們看看列子:

1,向裝置傳遞資料,我們定義一個函數來實作

bool CDeviceOperDlg::SendKeyData(HANDLE handle, BYTE *bData, int iSize)

{

 ULONG nOutput;

 BYTE bTemp[512];

 //将資料放置到發送數組

 memset(bTemp,0,sizeof(bTemp));

 memcpy(bTemp,&bData[0],iSize);

 //向裝置發送

 if (!DeviceIoControl(handle,        

       ATST2004_IOCTL_WRITE,     //根據具體的裝置有相關的定義

       bTemp,                                        //向裝置傳遞的資料位址

       iSize,                                            //資料大小,位元組數

       NULL,                                          //沒有傳回的資料,置為NULL

       0,                                                  //沒有傳回的資料,置為0

       &nOutput,

       NULL)

    )

 {

  return false;

 }

 return true;

}

2,從裝置讀取資料

bool CDeviceOperDlg::ReviceKeyData(HANDLE handle, BYTE *bData, int iSize)

{

 ULONG nOutput;

 BYTE bTemp[512];

 //數組清零

 memset(bTemp,0,sizeof(bTemp));

 //向裝置發送

 if (!DeviceIoControl(handle,

       ATST2004_IOCTL_READ,           //根據具體的裝置有相關的定義

       NULL,                                              //沒有向裝置傳遞的資料,置為NULL

       0,                                                      //沒有向裝置傳遞的資料,置為NULL

       bTemp,                                           //讀取裝置的資料傳回位址

       iSize,                                               //讀取資料的位元組數

       &nOutput,

       NULL)

    )

 {

  return false;

 }

 //放置到公用數組

 memcpy(&bData[0],&bTemp[0],iSize);

 return true;

}

---------------------------------------------------------------------------------

CTL_CODE說明

我們在說DeviceIoControl函數時其第二個參數dwIoControlCode就是由CTL_CODE宏定義的,下邊我們可以了解一下CTL_CODE的内容。

CTL_CODE:用于建立一個唯一的32位系統I/O控制代碼,這個控制代碼包括4部分組成:DeviceType(裝置類型,高16位(16-31位)),Access(通路限制,14-15位),Function(功能2-13位),Method(I/O通路記憶體使用方式)。

This macro creates a unique system I/O control code (IOCTL).

#define CTL_CODE(DeviceType, Function, Method, Access) (

  ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)

)Parameters(參數)

DeviceType

Defines the type of device for the given IOCTL.

This parameter can be no bigger than a WORD value.

The values used by Microsoft are in the range 0-32767; the values 32768-65535 are reserved for use by OEMs and IHVs.

The following device types are defined by the system:

FILE_DEVICE_BEEP

FILE_DEVICE_CD_ROM

FILE_DEVICE_CD_ROM_FILE_SYSTEM

FILE_DEVICE_CONTROLLER

FILE_DEVICE_DATALINK

FILE_DEVICE_DFS

FILE_DEVICE_DISK

FILE_DEVICE_DISK_FILE_SYSTEM

FILE_DEVICE_FILE_SYSTEM

FILE_DEVICE_INPORT_PORT

FILE_DEVICE_KEYBOARD

FILE_DEVICE_MAILSLOT

FILE_DEVICE_MIDI_IN

FILE_DEVICE_MIDI_OUT

FILE_DEVICE_MOUSE

FILE_DEVICE_MULTI_UNC_PROVIDER

FILE_DEVICE_NAMED_PIPE

FILE_DEVICE_NETWORK

FILE_DEVICE_NETWORK_BROWSER

FILE_DEVICE_NETWORK_FILE_SYSTEM

FILE_DEVICE_NULL

FILE_DEVICE_PARALLEL_PORT

FILE_DEVICE_PHYSICAL_NETCARD

FILE_DEVICE_PRINTER

FILE_DEVICE_SCANNER

FILE_DEVICE_SERIAL_MOUSE_PORT

FILE_DEVICE_SERIAL_PORT

FILE_DEVICE_SCREEN

FILE_DEVICE_SOUND

FILE_DEVICE_DEVICE_STREAMS

FILE_DEVICE_TAPE

FILE_DEVICE_TAPE_FILE_SYSTEM

FILE_DEVICE_TRANSPORT

FILE_DEVICE_UNKNOWN

FILE_DEVICE_VIDEO

FILE_DEVICE_VIRTUAL_DISK

FILE_DEVICE_WAVE_IN

FILE_DEVICE_WAVE_OUT

FILE_DEVICE_8042_PORT

FILE_DEVICE_NETWORK_REDIRECTOR

FILE_DEVICE_BATTERY

FILE_DEVICE_BUS_EXTENDER

FILE_DEVICE_MODEM

FILE_DEVICE_VDM

FILE_DEVICE_MASS_STORAGE

FILE_DEVICE_SMB

FILE_DEVICE_KS

FILE_DEVICE_CHANGER

FILE_DEVICE_SMARTCARD

FILE_DEVICE_ACPI

FILE_DEVICE_DVD

FILE_DEVICE_FULLSCREEN_VIDEO

FILE_DEVICE_DFS_FILE_SYSTEM

FILE_DEVICE_DFS_VOLUME

The following device types are specific to Windows CE:

FILE_DEVICE_HAL

FILE_DEVICE_CONSOLE

FILE_DEVICE_PSL

FILE_DEVICE_SERVICE

Function

Defines an action within the device category.

Function codes 0-2047 are reserved for Microsoft; codes 2048-4095 are reserved for OEMs and IHVs.

A function code can be no larger then 4095.

Method

Defines the method codes for how buffers are passed for I/O and file system controls.

The following values are possible for this parameter:

METHOD_BUFFERED

METHOD_IN_DIRECT

METHOD_OUT_DIRECT

METHOD_NEITHER

This field is ignored by Windows CE. You should always use the METHOD_BUFFERED value unless compatibility with Windows-based desktop platforms is required using a different Method value.

Access

Defines the access check value for any access.

The following table shows the possible flags for this parameter. The FILE_ACCESS_ANY is generally the correct value.

Flag Description

FILE_ANY_ACCESS Request all access.

FILE_READ_ACCESS Request read access. Can be used with FILE_WRITE_ACCESS.

FILE_WRITE_ACCESS Request write access. Can be used with FILE_READ_ACCESS.

Return Values(傳回值)

None.

Remarks(備注)

The macro can be used for defining IOCTL and FSCTL function control codes. All IOCTLs must be defined this way to ensure that values used by Microsoft, OEMs, and IHVs do not overlap.

The following illustration shows the format of the resulting IOCTL.

---------------------------------

|             |         |         |    |

31         16 15 14       2    1

---------------------------------

              |         |         |    |

DeviceType Access Function Method

---------------------------------

舉例說明一下:

我定義兩個IOCTL,一個用于對裝置的讀,一個用于對裝置的寫

#define ATST2004_IOCTL_READ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_READ_DATA)

#define ATST2004_IOCTL_WRITE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_WRITE_DATA)

在VC中使用不需要進行處理,假如我要在VB中使用這兩個IOCTL,就需要進行查值計算了,計算後定義如下:

Private Const ATST2004_IOCTL_READ = &H226000

Private Const ATST2004_IOCTL_WRITE = &H22A004

關于Method(I/O通路記憶體使用方式),我們下篇在說。

------------------------------------------------------------------------------------

CTL_CODE定義中Method的說明

我在上一篇中說明CTL_CODE的時候,其中CTL_CODE定義中有一個Method域,該域的功能意義是定義用于與在驅動程式中擷取應用程式資料緩沖區的位址方式。如果你看了我前邊的文章,你可以看到在DeviceIoControl的使用說明中對DeviceIoControl參數進行描述中關于lpInBuffer 和lpOutBuffer 的描述。簡單的說,Method域就是定義了lpInBuffer 和lpOutBuffer 緩沖區在驅動程式中對這兩個緩沖區位址的擷取和資料的操作方式。我們分别進行描述:

•METHOD_BUFFERED

系統配置設定一個緩沖區用于輸入和輸出,該緩沖區的位元組數應該為應用程式的輸入和輸出緩沖區中較大的位元組數。驅動程式中通過KIrp::IoctlBuffer獲得緩沖區的位址。對于輸出,驅動程式必須将輸出位元組數傳回給I.Information(),然後由I/O管理器将資料從系統緩沖區複制到應用程式的緩沖區中。

•METHOD_IN_DIRECT

•METHOD_OUT_DIRECT

在這兩種方式下,輸入緩沖區資料被複制到一個系統緩沖區中,驅動程式可以用KIrp::IoctlBuffer通路這個緩沖區。輸出緩沖區被類KMemory對象映射,驅動程式可以通過KIrp::Mdl來通路這個緩沖區。

•METHOD_NEITHER

這個比較特殊,一般不使用。

typedef   struct_OVERLAPPED

{

      DWORD   Internal;

      DWORD   InternalHigh;

      DWORD   offset;

      DWORD   offsetHigh;

      HANDLE   hEvent;

}OVERLAPPED;

Internal   指定與系統相關的狀态,為作業系統的使用而保留;

InternalHigh   指定傳送資料的長度,為作業系統的使用而保留;

offset   指定檔案的位置,從該位置傳送資料,檔案位置是相對檔案開始處的位元組偏移量。調用ReadFile或WriteFile函數之前調用程序設定這個成員,讀寫命名管道及通信裝置時調用程序忽略這個成員;

offsetHigh   指定開始傳送資料的位元組偏移量的高位字,讀寫命名管道及通信裝置時調用程序忽略這個成員;

hEvent   辨別事件,資料傳送完成時把它設為信号狀态,調用ReadFile   WriteFile   ConnectNamedPipe   TransactNamedPipe函數前,調用程序設定這個成員.

相關函數   CreateEvent     ResetEvent   GetOverlappedResult   WaitForSingleObject   CWinThread   GetLastErro  

繼續閱讀