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

WdfDeviceIoNeither


參考資訊:
1. Source Code

WdfDeviceIoNeither的意思就是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

記憶體指標:

Event Buffer Length
EvtIoRead Step 1. WdfRequestRetrieveUnsafeUserOutputBuffer()
Step 2. WdfRequestProbeAndLockUserBufferForWrite()
Step 3. WdfMemoryGetBuffer()
傳入的第三個參數
EvtIoWrite Step 1. WdfRequestRetrieveUnsafeUserInputBuffer()
Step 2. WdfRequestProbeAndLockUserBufferForRead()
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

.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

.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

IrpRead proc Queue:WDFQUEUE, Request:WDFREQUEST, _Length:DWORD
  local len:dword
  local buf:dword
  local memory:WDFMEMORY
  
  invoke DbgPrint, $CTA0("IrpRead")
  invoke WdfRequestRetrieveUnsafeUserOutputBuffer, Request, _Length, addr buf, addr len
  invoke WdfRequestProbeAndLockUserBufferForWrite, Request, buf, len, addr memory
  invoke strlen, offset szBuffer
  inc eax
  mov len, eax
  invoke WdfMemoryGetBuffer, memory, NULL
  invoke memcpy, eax, offset szBuffer, len
  invoke WdfRequestCompleteWithInformation, Request, STATUS_SUCCESS, len
  ret
IrpRead endp

IrpWrite proc Queue:WDFQUEUE, Request:WDFREQUEST, _Length:DWORD
  local len:dword
  local buf:dword
  local memory:WDFMEMORY
  
  invoke DbgPrint, $CTA0("IrpWrite")
  invoke WdfRequestRetrieveUnsafeUserInputBuffer, Request, _Length, addr buf, addr len
  invoke WdfRequestProbeAndLockUserBufferForRead, Request, buf, len, addr memory
  invoke WdfMemoryGetBuffer, memory, NULL
  invoke memcpy, offset szBuffer, eax, _Length
  invoke DbgPrint, $CTA0("Buffer: %s, Length:%d"), offset szBuffer, _Length
  invoke WdfRequestCompleteWithInformation, Request, STATUS_SUCCESS, _Length
  ret
IrpWrite 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, WdfDeviceIoNeither
  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]).EvtIoRead, offset IrpRead
  mov (WDF_IO_QUEUE_CONFIG ptr [eax]).EvtIoWrite, offset IrpWrite
  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

IrpWrite()複製User Application的資料到szBuffer
IrpRead()回填資料給User Application
P.S. 值得注意的是,Lock後的buf也可以拿來使用,只是目前遵照WDF寫法,透過WdfMemoryGetBuffer()統一取得可用的指標。

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

includelib c:\masm32\lib\user32.lib
includelib c:\masm32\lib\masm32.lib
includelib c:\masm32\lib\msvcrt.lib
includelib c:\masm32\lib\kernel32.lib

.const
DEV_NAME db "\\.\MyDriver",0
MSG_ERR  db "failed to open mydriver",10,13,0
MSG_SEND db "I am error",0
MSG_WR   db "WR: %s, %d",10,13,0
MSG_RD   db "RD: %s, %d",10,13,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, offset MSG_ERR
    invoke ExitProcess, -1
  .endif
  
  mov hFile, eax
  invoke StrLen, offset MSG_SEND
  inc eax
  mov dwRet, eax
  invoke crt_printf, offset MSG_WR, offset MSG_SEND, eax
  invoke WriteFile, hFile, offset MSG_SEND, dwRet, offset dwRet, 0
  invoke crt_memset, offset szBuffer, 0, 255
  invoke ReadFile, hFile, offset szBuffer, 255, offset dwRet, 0
  invoke crt_printf, offset MSG_RD, offset szBuffer, dwRet
  invoke CloseHandle, hFile
  invoke ExitProcess, 0
  
end start

結果


返回上一頁