User Application和驅動程式必須定義一致的IOCTL,雙方才可以正確識別,IOCTL可以透過CTL_CODE()做定義,如下範例:
#define IOCTL_TEST CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS) int __cdecl main(int argc, char **argv) { ... DeviceIoControl(hFile, IOCTL_TEST, NULL, 0, NULL, 0, &dwRet, NULL); ... }
第三個參數用來描述Buffer的處理方式,分為Buffered、Direct和Neither三種處理方式,針對每種處理方式,司徒整理如下表格:
使用方式 | 行為描述 |
---|---|
METHOD_BUFFERED | I/O Manager會新增一塊跟User Buffer一樣大小的記憶體,讀寫都需要由I/O Manager負責同步更新(進行複製的動作) |
METHOD_IN_DIRECT、METHOD_OUT_DIRECT | I/O Manager會Mapping User Buffer到一個MDL(Memory Description List),驅動程式使用這個MDL進行操作,相較於METHOD_BUFFERED,因為資料不須由I/O Manager做複製的動作,因此,效率會比較好 |
METHOD_NEITHER | I/O Manager會將Use Buffer Pointer,透過特殊操作後,再傳遞給驅動程式使用,因為,驅動程式可以直接存取User Buffer的資料,因此,效率是這三種方式裡面最好的一個 |
驅動程式必須依據Buffer的設定去存取不同欄位的Pointer,這樣才可以正確存取到User Buffer
使用方式 | Buffer Type | Buffer Pointer | Buffer Length |
---|---|---|---|
METHOD_BUFFERED | Input | (IRP) AssociatedIrp.SystemBuffer | (IrpStack) Parameters.DeviceIoControl.InputBufferLength |
Output | (IRP) AssociatedIrp.SystemBuffer | (IrpStack) Parameters.DeviceIoControl.OutputBufferLength | |
METHOD_IN_DIRECT | Input | (MDL) AssociatedIrp.SystemBuffer | (IrpStack) Parameters.DeviceIoControl.InputBufferLength |
METHOD_OUT_DIRECT | Output | (MDL) MmGetSystemAddressForMdlSafe | (IrpStack) Parameters.DeviceIoControl.OutputBufferLength |
METHOD_NEITHER | Input | (IrpStack) Parameters.DeviceIoControl.Type3InputBuffer | (IrpStack) Parameters.DeviceIoControl.InputBufferLength |
Output | (IRP) UserBuffer | (IrpStack) Parameters.DeviceIoControl.OutputBufferLength |