分享
 
 
 

DeviceIoControl接口

王朝c/c++·作者佚名  2006-01-06
窄屏简体版  字體: |||超大  

DeviceIoControl接口

在这一节中我们将要关于学习动态VXD,特别是如何创建,加载和使用。

点击这里下载例子

VxD接口

VxD总共提供了4种接口。

l VxD services VxD服务

l V86 Interface V86接口

l Protected-mode (PM) Interface 保护模式接口

l Win32 DeviceIoControl Interface Win32设备输入输出控制接口

我们已经知道了VxD服务,V86和保护模式接口是由V86和保护模式程序调用的。因为V86和保护模式程序是16位的,我们不能在Win32应用程序中使用那两种接口。在Windows 95中,微软给Win32应用程序加了另外一个接口所以Win32应用程序可以调用VxD的服务:DeviceIoControl接口(设备输入输出控制接口)

DeviceIoControl接口

简单的说,DeviceIoControl接口是一种为Win32程序准备的调用VxD内部函数的方法。不要混淆DeviceIoControl接口调用函数和用VxD服务调用函数,这两种方法是不一样的。比如说,DeviceIoControl function1 也许和Vxd service1是不一样的。你应给把DeviceIoControl函数作为一种只为Win32应用程序提供的单独的函数。

在Win32程序方面:

首先用CreateFile来打开/加载一个VxD。如果调用成功的话,VxD将会创建/加再到内存中并且CreateFile把VxD的句柄返回到eax中。

接着你调用DeviceIoControlAPI函数来选择要运行的函数。DeviceIoControl函数遵循下面的语法:

DeviceIoControl PROTO hDevice:DWORD,\

dwIoControlCode:DWORD,\

lpInBuffer:DWORD,\

nInBufferSize:DWORD,\

lpOutBuffer:DWORD,\

nOutBufferSize:DWORD,\

lpBytesReturned:DWORD,\

lpOverlapped:DWORD

l hDevice 是从CreateFile返回的VxD句柄。

l dwIoControlCode是用来制定VxD将要进行的操作。你应该在你要选用那种操作之前得到可能的dwIoControlCode值得列表。

l lpInBuffer是包含了VxD完成dwIoControlCode所制定操作的数据的缓冲区地址。如果这个操作不需要数据,你可以传为NULL。

l nInBufferSize是由lpInBuffer所指向的缓冲区的地址的大小(byte)。

l lpOutBuffer是VxD程序在操作成功之后要将输出数据输出到的缓冲区。如果这个操作没有任何返回值,这个值可以为NULL。

l nOutBufferSize是lpOutBuffer所指向的缓冲区的大小(byte)。

l lpBytesReturned是一个dword型变量的地址。这个变量用来接收VxD在lpOutBuffer中写入数据的大小。

l 如果你想要把操作设成异步的,lpOverlapped是一个OVERLAPPED结构的指针。如果你要一直等直到操作完成,这个值为NULL。

在VxD方面:

VxD程序必须处理w32_deviceIoControl消息。当VxD收到w32_deviceIoControl消息,它的寄存器是如下值:

l ebx 是VM的句柄。

l esi 是指向DIOCParams结构的指针。DIOCParams包含了从win32程序传送的信息。

DIOCParams是按照如下定义的:

DIOCParams STRUC

Internal1 DD ?

VMHandle DD ?

Internal2 DD ?

dwIoControlCode DD ?

lpvInBuffer DD ?

cbInBuffer DD ?

lpvOutBuffer DD ?

cbOutBuffer DD ?

lpcbBytesReturned DD ?

lpoOverlapped DD ?

hDevice DD ?

tagProcess DD ?

DIOCParams ENDS

l Internal1 是指向Win32应用应用程序用户寄存器结构的指针。

l VMHandle 虚拟机句柄

l Internal2 是指向设备描述块(DDB)的句柄。

l dwIoControlCode, lpvInBuffer, cbInBuffer, lpvOutBuffer, cbOutBuffer, lpcbBytesReturned, lpOverlapped是传送到DeviceIoControl API的参数。

l hDevice是 ring-3级设备句柄。

l tagProces 是过程的标签。

在DIOCParams结构中有所有从Win32应用程序传送到你的VxD的信息。

你的VxD至少要处理DIOC_Open(传送到dwIoControlCode),那是当Win32程序调用CreateFile打开你的VxD时VWIN32发送给你的VxD的。如果你的VxD准备好了,它必须在eax中返回0而且CreateFile也会成功。如果你的VxD没有准备好,它必须在eas中返回一个非零值而且CreateFile也会失败。除了DIOC_Open,当Win32程序关闭这个设备句柄时,你的VxD将会从VWIN32收到DIOC_Closehandle。

能由CreateFile加载的最小的动态VxD框架:

.386p

include vmm.inc

include vwin32.inc

DECLARE_VIRTUAL_DEVICE DYNAVXD,1,0, DYNAVXD_Control,\

UNDEFINED_DEVICE_ID, UNDEFINED_INIT_ORDER

Begin_control_dispatch DYNAVXD

Control_Dispatch w32_DeviceIoControl, OnDeviceIoControl

End_control_dispatch DYNAVXD

VxD_PAGEABLE_CODE_SEG

BeginProc OnDeviceIoControl

assume esi:ptr DIOCParams

.if [esi].dwIoControlCode==DIOC_Open

xor eax,eax

.endif

ret

EndProc OnDeviceIoControl

VxD_PAGEABLE_CODE_ENDS

end

;--------------------------------------------------------------------------------------------------------------------------------

; Module Definition File

;---------------------------------------------------------------------------------------------------------------------------------

VXD DYNAVXD DYNAMIC

SEGMENTS

_LPTEXT CLASS 'LCODE' PRELOAD NONDISCARDABLE

_LTEXT CLASS 'LCODE' PRELOAD NONDISCARDABLE

_LDATA CLASS 'LCODE' PRELOAD NONDISCARDABLE

_TEXT CLASS 'LCODE' PRELOAD NONDISCARDABLE

_DATA CLASS 'LCODE' PRELOAD NONDISCARDABLE

CONST CLASS 'LCODE' PRELOAD NONDISCARDABLE

_TLS CLASS 'LCODE' PRELOAD NONDISCARDABLE

_BSS CLASS 'LCODE' PRELOAD NONDISCARDABLE

_LMGTABLE CLASS 'MCODE' PRELOAD NONDISCARDABLE IOPL

_LMSGDATA CLASS 'MCODE' PRELOAD NONDISCARDABLE IOPL

_IMSGTABLE CLASS 'MCODE' PRELOAD DISCARDABLE IOPL

_IMSGDATA CLASS 'MCODE' PRELOAD DISCARDABLE IOPL

_ITEXT CLASS 'ICODE' DISCARDABLE

_IDATA CLASS 'ICODE' DISCARDABLE

_PTEXT CLASS 'PCODE' NONDISCARDABLE

_PMSGTABLE CLASS 'MCODE' NONDISCARDABLE IOPL

_PMSGDATA CLASS 'MCODE' NONDISCARDABLE IOPL

_PDATA CLASS 'PDATA' NONDISCARDABLE SHARED

_STEXT CLASS 'SCODE' RESIDENT

_SDATA CLASS 'SCODE' RESIDENT

_DBOSTART CLASS 'DBOCODE' PRELOAD NONDISCARDABLE CONFORMING

_DBOCODE CLASS 'DBOCODE' PRELOAD NONDISCARDABLE CONFORMING

_DBODATA CLASS 'DBOCODE' PRELOAD NONDISCARDABLE CONFORMING

_16ICODE CLASS '16ICODE' PRELOAD DISCARDABLE

_RCODE CLASS 'RCODE'

EXPORTS

DYNAVXD_DDB @1

完整例子:

下面是一段加载动态VxD并且通过DeviceIoControl API 来调用VxD内部函数的Win32应用程序的源代码。

; VxDLoader.asm

.386

.model flat,stdcall

include windows.inc

include kernel32.inc

includelib kernel32.lib

include user32.inc

includelib user32.lib

.data

AppName db "DeviceIoControl",0

VxDName db "\\.\shellmsg.vxd",0

Success db "The VxD is successfully loaded!",0

Failure db "The VxD is not loaded!",0

Unload db "The VxD is now unloaded!",0

MsgTitle db "DeviceIoControl Example",0

MsgText db "I'm called from a VxD!",0

InBuffer dd offset MsgTitle

dd offset MsgText

.data?

hVxD dd ?

.code

start:

invoke CreateFile,addr VxDName,0,0,0,0,FILE_FLAG_DELETE_ON_CLOSE,0

.if eax!=INVALID_HANDLE_VALUE

mov hVxD,eax

invoke MessageBox,NULL,addr Success,addr AppName,MB_OK+MB_ICONINFORMATION

invoke DeviceIoControl,hVxD,1,addr InBuffer,8,NULL,NULL,NULL,NULL

invoke CloseHandle,hVxD

invoke MessageBox,NULL,addr Unload,addr AppName,MB_OK+MB_ICONINFORMATION

.else

invoke MessageBox,NULL,addr Failure,NULL,MB_OK+MB_ICONERROR

.endif

invoke ExitProcess,NULL

end start

下面这段源代码是由 vxdloader.asm 调用的动态VxD。

; ShellMsg.asm

.386p

include vmm.inc

include vwin32.inc

include shell.inc

DECLARE_VIRTUAL_DEVICE SHELLMSG,1,0, SHELLMSG_Control,\

UNDEFINED_DEVICE_ID, UNDEFINED_INIT_ORDER

Begin_control_dispatch SHELLMSG

Control_Dispatch w32_DeviceIoControl, OnDeviceIoControl

End_control_dispatch SHELLMSG

VxD_PAGEABLE_DATA_SEG

pTitle dd ?

pMessage dd ?

VxD_PAGEABLE_DATA_ENDS

VxD_PAGEABLE_CODE_SEG

BeginProc OnDeviceIoControl

assume esi:ptr DIOCParams

.if [esi].dwIoControlCode==DIOC_Open

xor eax,eax

.elseif [esi].dwIoControlCode==1

mov edi,[esi].lpvInBuffer

;-----------------------------------

; copy the message title to buffer

;-----------------------------------

VMMCall _lstrlen, <[edi]>

inc eax

push eax

VMMCall _HeapAllocate,<eax,HEAPZEROINIT>

mov pTitle,eax

pop eax

VMMCall _lstrcpyn,<pTitle,[edi],eax>

;-----------------------------------

; copy the message text to buffer

;-----------------------------------

VMMCall _lstrlen, <[edi+4]>

inc eax

push eax

VMMCall _HeapAllocate,<eax,HEAPZEROINIT>

mov pMessage,eax

pop eax

VMMCall _lstrcpyn,<pMessage,[edi+4],eax>

mov edi,pTitle

mov ecx,pMessage

mov eax,MB_OK

VMMCall Get_Sys_VM_Handle

VxDCall SHELL_sysmodal_Message

VMMCall _HeapFree,pTitle,0

VMMCall _HeapFree,pMessage,0

xor eax,eax

.endif

ret

EndProc OnDeviceIoControl

VxD_PAGEABLE_CODE_ENDS

end

分析:

我们从VxDLoader.asm开始。

Invoke CreateFile,addrVxDName,0,0,0,0,FILE_FLAG_DELETE_ON_CLOSE,0

.if eax!=INVALID_HANDLE_VALUE

mov hVxD,eax

....

.else

invoke MessageBox,NULL,addr Failure,NULL,MB_OK+MB_ICONERROR

.endif

我们调用CreateFile来加载动态VxD。注意FILE_FLAG_DELETE_ON_CLOSE标记。当从CreateFile返回的VxD句柄被关闭的时候,这个标志通知Windows卸载VxD。如果CreateFile成功,我们把VxD句柄保存起来。

invoke MessageBox,NULL,addr Success,addr AppName,MB_OK+MB_ICONINFORMATION

invoke DeviceIoControl,hVxD,1,addr InBuffer,8,NULL,NULL,NULL,NULL

invoke CloseHandle,hVxD

invoke MessageBox,NULL,addr Unload,addr AppName,MB_OK+MB_ICONINFORMATION

当VxD加载/卸载的时候,这个程序会显示一个消息框。它令dwIoControlCode=1然后调用DeviceIoControl。将InBuffer的地址传给lpInBuffer,将InBuffer的大小传给nInBufferSize。InBuffer是一个包括两个元素的数组:每个元素都是一个字符串的地址。

MsgTitle db "DeviceIoControl Example",0

MsgText db "I'm called from a VxD!",0

InBuffer dd offset MsgTitle

dd offset MsgText

现在我们看一下这段VxD。

它只处理w32_deviceIoControl消息。当w32_deviceIoControl消息发送的时候,调用OnDeviceIoControl函数。

BeginProc OnDeviceIoControl

assume esi:ptr DIOCParams

.if [esi].dwIoControlCode==DIOC_Open

xor eax,eax

OnDeviceIoControl 处理DIOC_Open,再eas中返回0。

.elseif [esi].dwIoControlCode==1

mov edi,[esi].lpvInBuffer

它也处理control code 等于1。它做的第一件事是取出在lpyInBuffer中的数据。这个数据是传送到DeviceIoControl API 的lpInBuffer中的两个dword值。它把指向dword数组的地址放到edi中。第一个dword是作为消息框标题的字符串地址。第二个dword是作为消息框文本的字符串地址。

;-----------------------------------

; copy the message title to buffer

;-----------------------------------

VMMCall _lstrlen, <[edi]>

inc eax

push eax

VMMCall _HeapAllocate,<eax,HEAPZEROINIT>

mov pTitle,eax

pop eax

VMMCall _lstrcpyn,<pTitle,[edi],eax>

它调用VMM服务lstrlen来计算消息框标题的长度。lstrlen在eax中返回字符串的长度。我们把这个长度加1来包括结束标记NULL。下一步我们通过调用HeapAllocate来分配一块足够大可以容纳字符串和它的结束标记NULL内存。加上HEAPZEROINIT标记使HeapAllocate将这块内存清零。HeapAllocate在eax中返回这块内存的地址。我们然后从win32 app的地址空间把字符串拷贝到我们申请的内存中。我们对要做消息框文本的字符串做同样的操作。

mov edi,pTitle

mov ecx,pMessage

mov eax,MB_OK

VMMCall Get_Sys_VM_Handle

VxDCall SHELL_sysmodal_Message

我们把标题和文本的地址分别存在edi和ecx中。把想要的标记放在eax中,通过调用Get_Sys_VM_handle得到系统VM的VM 句柄。然后调用SHELL_sysbodal_Message 。SHELL_sysModal_Message是系统SHELL_Message的模式版本。它冻结系统直到用户对消息框做出反应。

VMMCall _HeapFree,pTitle,0

VMMCall _HeapFree,pMessage,0

当SHELL_sysmodal_Message返回时,我们用_HeapFree释放内存。

总结:

DeviceIoControl接口使你的win32应用程序使用动态VxD作为一个ring-0 DLL扩展非常理想。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有