Kernel Mode Driver Framework >> Assembly (PNP) >> IOCTL

METHOD_NEITHER


參考資訊:
1. Source Code

Neither I/O(METHOD_NEITHER)的意思就是Neither Buffered Nor Direct I/O,使用這種方式時,I/O Manager會將User Buffer的指標,透過操作後,傳遞給驅動程式使用,因此,驅動程式可以直接存取User Buffer的資料,所以存取速度可以得到很大的改善,對於有速度要求的驅動程式來說,建議使用Neither的方式,不過,關於User Buffer指標的存取問題上,會遇到更多需要面對的問題,如:指標的有效性以及多次存取的同步問題,因此,在選擇使用上,更需要考量到這些額外付出的代價是否值得使用,因為,驅動程式以及User Application雙方都需要很嚴謹的看待這塊共用的Buffer。

Microsoft的說明網頁:
using-neither-buffered-nor-direct-i-o

記憶體指標:

Buffer Length
Input Step 1. WdfRequestRetrieveUnsafeUserInputBuffer()
Step 2. WdfRequestProbeAndLockUserBufferForRead()
Step 3. WdfMemoryGetBuffer()
傳入的第四個參數
Output Step 1. WdfRequestRetrieveUnsafeUserOutputBuffer()
Step 2. WdfRequestProbeAndLockUserBufferForWrite()
Step 3. WdfMemoryGetBuffer()
傳入的第三個參數

main.asm

.386p
.model flat, stdcall
option casemap:none

include c:\masm32\Macros\Strings.mac
include c:\masm32\include\w2k\ntdef.inc
include c:\masm32\include\w2k\ntstatus.inc
include c:\masm32\include\w2k\ntddk.inc
include c:\masm32\include\w2k\ntoskrnl.inc
include c:\masm32\include\w2k\ntddkbd.inc
include c:\masm32\include\wxp\wdm.inc
include c:\masm32\include\wdf\umdf\1.9\wudfddi_types.inc
include c:\masm32\include\wdf\kmdf\1.9\wdf.inc
include c:\masm32\include\wdf\kmdf\1.9\wdftypes.inc
include c:\masm32\include\wdf\kmdf\1.9\wdfglobals.inc
include c:\masm32\include\wdf\kmdf\1.9\wdffuncenum.inc
include c:\masm32\include\wdf\kmdf\1.9\wdfobject.inc
include c:\masm32\include\wdf\kmdf\1.9\wdfdevice.inc
include c:\masm32\include\wdf\kmdf\1.9\wdfdriver.inc
include c:\masm32\include\wdf\kmdf\1.9\wdfrequest.inc
include c:\masm32\include\wdf\kmdf\1.9\wdfio.inc
include c:\masm32\include\wdf\kmdf\1.9\wdfmemory.inc

includelib c:\masm32\lib\wxp\i386\BufferOverflowK.lib 
includelib c:\masm32\lib\wxp\i386\ntoskrnl.lib 
includelib c:\masm32\lib\wxp\i386\hal.lib 
includelib c:\masm32\lib\wxp\i386\wmilib.lib 
includelib c:\masm32\lib\wxp\i386\sehupd.lib 
includelib c:\masm32\lib\wdf\kmdf\i386\1.9\wdfldr.lib
includelib c:\masm32\lib\wdf\kmdf\i386\1.9\wdfdriverentry.lib

public DriverEntry

IOCTL_GET equ CTL_CODE(FILE_DEVICE_UNKNOWN, 800h, METHOD_NEITHER, FILE_ANY_ACCESS)
IOCTL_SET equ CTL_CODE(FILE_DEVICE_UNKNOWN, 801h, METHOD_NEITHER, FILE_ANY_ACCESS)

.const
DEV_NAME word "\","D","e","v","i","c","e","\","M","y","D","r","i","v","e","r",0
SYM_NAME word "\","D","o","s","D","e","v","i","c","e","s","\","M","y","D","r","i","v","e","r",0
MSG_GET byte "IOCTL_GET",0
MSG_SET byte "IOCTL_SET",0

.data
szBuffer byte 255 dup(0)

.code
IrpFileCreate proc Device:WDFDEVICE, Request:WDFREQUEST, FileObject:WDFFILEOBJECT
  invoke DbgPrint, $CTA0("IrpFieCreate")
  invoke WdfRequestComplete, Request, STATUS_SUCCESS
  ret
IrpFileCreate endp

IrpFileClose proc FileObject:WDFFILEOBJECT
  invoke DbgPrint, $CTA0("IrpFieClose")
  ret
IrpFileClose endp

IrpIOCTL proc Queue:WDFQUEUE, Request:WDFREQUEST, OutputBufferLength:DWORD, InputBufferLength:DWORD, IoControlCode:DWORD
  local len:dword
  local buf:dword
  local memory:WDFMEMORY
  
  .if IoControlCode == IOCTL_SET
    invoke DbgPrint, offset MSG_SET
    invoke WdfRequestRetrieveUnsafeUserInputBuffer, Request, InputBufferLength, addr buf, addr len
    invoke WdfRequestProbeAndLockUserBufferForRead, Request, buf, len, addr memory
    invoke WdfMemoryGetBuffer, memory, NULL
    invoke memcpy, offset szBuffer, eax, InputBufferLength
    invoke DbgPrint, $CTA0("Buffer: %s, Length:%d"), offset szBuffer, InputBufferLength
    invoke WdfRequestSetInformation, Request, InputBufferLength
  .elseif IoControlCode == IOCTL_GET
    invoke DbgPrint, offset MSG_GET
    invoke WdfRequestRetrieveUnsafeUserOutputBuffer, Request, OutputBufferLength, addr buf, addr len
    invoke WdfRequestProbeAndLockUserBufferForWrite, Request, buf, len, addr memory
    invoke WdfMemoryGetBuffer, memory, NULL
    invoke memcpy, eax, offset szBuffer, OutputBufferLength
    invoke strlen, offset szBuffer
    inc eax
    invoke WdfRequestSetInformation, Request, eax
  .endif
  invoke WdfRequestComplete, Request, STATUS_SUCCESS
  ret
IrpIOCTL endp

AddDevice proc Driver:WDFDRIVER, pDeviceInit:PWDFDEVICE_INIT
  local device:WDFDEVICE
  local suDevName:UNICODE_STRING
  local szSymName:UNICODE_STRING
  local file_cfg:WDF_FILEOBJECT_CONFIG
  local ioqueue_cfg:WDF_IO_QUEUE_CONFIG

  invoke RtlInitUnicodeString, addr suDevName, offset DEV_NAME
  invoke RtlInitUnicodeString, addr szSymName, offset SYM_NAME
  invoke WdfDeviceInitAssignName, pDeviceInit, addr suDevName
  invoke WdfDeviceInitSetIoType, pDeviceInit, WdfDeviceIoBuffered
  invoke WDF_FILEOBJECT_CONFIG_INIT, addr file_cfg, offset IrpFileCreate, offset IrpFileClose, NULL
  invoke WdfDeviceInitSetFileObjectConfig, pDeviceInit, addr file_cfg, WDF_NO_OBJECT_ATTRIBUTES
  invoke WdfDeviceCreate, addr pDeviceInit, WDF_NO_OBJECT_ATTRIBUTES, addr device
  invoke WdfDeviceCreateSymbolicLink, device, addr szSymName
  invoke WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE, addr ioqueue_cfg, WdfIoQueueDispatchSequential
  lea eax, ioqueue_cfg
  mov (WDF_IO_QUEUE_CONFIG ptr [eax]).EvtIoDeviceControl, offset IrpIOCTL
  invoke WdfIoQueueCreate, device, addr ioqueue_cfg, WDF_NO_OBJECT_ATTRIBUTES, WDF_NO_HANDLE
  ret
AddDevice endp

DriverEntry proc pOurDriver:PDRIVER_OBJECT, pOurRegistry:PUNICODE_STRING
  local config:WDF_DRIVER_CONFIG
  
  invoke WDF_DRIVER_CONFIG_INIT, addr config, AddDevice
  invoke WdfDriverCreate, pOurDriver, pOurRegistry, WDF_NO_OBJECT_ATTRIBUTES, addr config, WDF_NO_HANDLE
  ret
DriverEntry endp
end DriverEntry
.end

IrpIOCTL()收到IOCTL_SET時,Driver複製User Buffer的內容到szBuffer,而收到IOCTL_GET時,將szBuffer內容又複製回User Buffer,完成暫存的功能。

app.asm

.386p
.model flat, stdcall
option casemap:none

include c:\masm32\include\windows.inc
include c:\masm32\include\masm32.inc
include c:\masm32\include\user32.inc
include c:\masm32\include\msvcrt.inc
include c:\masm32\include\kernel32.inc
include c:\masm32\include\w2k\ntddkbd.inc
include c:\masm32\Macros\Strings.mac
 
includelib c:\masm32\lib\user32.lib
includelib c:\masm32\lib\masm32.lib
includelib c:\masm32\lib\msvcrt.lib
includelib c:\masm32\lib\kernel32.lib

IOCTL_GET equ CTL_CODE(FILE_DEVICE_UNKNOWN, 800h, METHOD_NEITHER, FILE_ANY_ACCESS)
IOCTL_SET equ CTL_CODE(FILE_DEVICE_UNKNOWN, 801h, METHOD_NEITHER, FILE_ANY_ACCESS)
 
.const
DEV_NAME db "\\.\MyDriver",0
 
.data?
hFile    dd ?
dwRet    dd ?
szBuffer db 255 dup(?)
 
.code
start:
  invoke CreateFile, offset DEV_NAME, GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0
  .if eax == INVALID_HANDLE_VALUE
    invoke crt_printf, $CTA0("failed to open mydriver")
    invoke ExitProcess, -1
  .endif
  
  mov hFile, eax
  invoke wsprintf, offset szBuffer, $CT0("I am error")
  invoke StrLen, offset szBuffer
  inc eax
  mov dwRet, eax
  invoke crt_printf, $CTA0("WR: %s, %d\n"), offset szBuffer, dwRet
  invoke DeviceIoControl, hFile, IOCTL_SET, offset szBuffer, dwRet, NULL, 0, offset dwRet, NULL
  invoke crt_memset, offset szBuffer, 0, 255
  invoke DeviceIoControl, hFile, IOCTL_GET, NULL, 0, offset szBuffer, 255, offset dwRet, NULL
  invoke crt_printf, $CTA0("RD: %s, %d\n"), offset szBuffer, dwRet
  invoke CloseHandle, hFile
  invoke ExitProcess, 0
  
end start

結果


返回上一頁