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
結果