📄 vxd-e4.html
字号:
<ul>
<br><b><font face="Arial,Helvetica"><font color="#66FF99"><font size=-1>\\.\pathname</font></font></font></b></ul>
<p><br><font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>For
example, if you want to load a dynamic VxD named FirstVxD which is in the
current directory, you should do it as follows:</font></font></font>
<p><b><font face="Arial,Helvetica"><font color="#FFCC33"><font size=-1>.data</font></font></font></b>
<br><b><font face="Arial,Helvetica"><font color="#FFCC33"><font size=-1>VxDName
db "\\.\FirstVxD.VXD",0</font></font></font></b>
<br><b><font face="Arial,Helvetica"><font color="#FFCC33"><font size=-1>......</font></font></font></b>
<br><b><font face="Arial,Helvetica"><font color="#FFCC33"><font size=-1>.data?</font></font></font></b>
<br><b><font face="Arial,Helvetica"><font color="#FFCC33"><font size=-1>hDevice
dd ?</font></font></font></b>
<br><b><font face="Arial,Helvetica"><font color="#FFCC33"><font size=-1>.....</font></font></font></b>
<br><b><font face="Arial,Helvetica"><font color="#FFCC33"><font size=-1>.code</font></font></font></b>
<br><b><font face="Arial,Helvetica"><font color="#FFCC33"><font size=-1>.....</font></font></font></b>
<br><b><font face="Arial,Helvetica"><font color="#FFCC33"><font size=-1>invoke
CreateFile, addr VxDName,0,0,0,0, FILE_FLAG_DELETE_ON_CLOSE,0</font></font></font></b>
<br><b><font face="Arial,Helvetica"><font color="#FFCC33"><font size=-1>mov
hDevice,eax</font></font></font></b>
<br><b><font face="Arial,Helvetica"><font color="#FFCC33"><font size=-1>......</font></font></font></b>
<br><b><font face="Arial,Helvetica"><font color="#FFCC33"><font size=-1>invoke
CloseHandle,hDevice</font></font></font></b>
<br><b><font face="Arial,Helvetica"><font color="#FFCC33"><font size=-1>......</font></font></font></b>
<br> </ul>
<font face="Arial,Helvetica"><font size=-1><b><font color="#FFFF99">FILE_FLAG_DELETE_ON_CLOSE</font></b><font color="#FFFFFF">
flag specifies that the VxD is unloaded when the handle returned by </font><b><font color="#FFFF99">CreateFile</font></b><font color="#FFFFFF">
is closed.</font></font></font>
<br><font face="Arial,Helvetica"><font size=-1><font color="#FFFFFF">If
you use CreateFile to load a dynamic VxD, the VxD </font><b><font color="#FFFF99">must
</font></b><font color="#FFFFFF">handle
</font><b><font color="#FFFF99">w32_DeviceIoControl
</font></b><font color="#FFFFFF">message.
</font><b><font color="#FFFF99">VWIN32
</font></b><font color="#FFFFFF">sends
this control message to your dynamic VxD when it is first loaded by CreateFile
method. Your VxD must return 0 in eax in response to this message. </font><b><font color="#FFFF99">w32_DeviceIoControl</font></b><font color="#FFFFFF">
messages are also sent when the application calls </font><b><font color="#FFFF99">DeviceIoControl</font></b><font color="#FFFFFF">
API to communicate with the VxD. We will examine </font><b><font color="#FFFF99">DeviceIoControl</font></b><font color="#FFFFFF">
interface in the later tutorial.</font></font></font>
<br><font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>A
dynamic VxD receives one message during initialization:</font></font></font>
<ul>
<li>
<b><font face="Arial,Helvetica"><font color="#FFFF99"><font size=-1>Sys_Dynamic_Device_Init</font></font></font></b></li>
</ul>
<font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>And one
control message during termination:</font></font></font>
<ul>
<li>
<b><font face="Arial,Helvetica"><font color="#FFFF99"><font size=-1>Sys_Dynamic_Device_Exit</font></font></font></b></li>
</ul>
<font face="Arial,Helvetica"><font size=-1><font color="#FFFFFF">A dynamic
VxD won't receive </font><b><font color="#FFFF99">Sys_Critical_Init</font></b><font color="#FFFFFF">,
</font><b><font color="#FFFF99">Device_Init</font></b><font color="#FFFFFF">
and </font><b><font color="#FFFF99">Init_Complete</font></b><font color="#FFFFFF">
control messages because those messages are sent during system VM initialization.
Other than that, dynamic VxDs receives all other control messages when
it's in memory. It can do anything a static VxD can do. In short, a dynamic
VxD is loaded with different mechanisms and receives different initialization/termination
control messages, other than that, it can do anything a static VxD can
do.</font></font></font>
<h3>
<font face="Arial,Helvetica"><font color="#66FFFF"><font size=+0>Other
System Control Messages</font></font></font></h3>
<font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>During
the time a VxD stays in memory, it will receive many control messages other
than those related to initialization and termination. Some of them are
related to virtual machine management and some to miscellaneous events.
For example, VM-related control messages are:</font></font></font>
<ul>
<li>
<font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>Create_VM</font></font></font></li>
<li>
<font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>VM_Critical_Init</font></font></font></li>
<li>
<font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>VM_Suspend</font></font></font></li>
<li>
<font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>VM_Resume</font></font></font></li>
<li>
<font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>Close_VM_Notify</font></font></font></li>
<li>
<font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>Destroy_VM</font></font></font></li>
</ul>
<font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>It's your
responsibility to choose to respond to the control messages you're interested
in.</font></font></font>
<h3>
<font face="Arial,Helvetica"><font color="#66FFFF"><font size=+0>Creating
procedures inside VxD</font></font></font></h3>
<font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>You declare
a procedure in VxD inside a segment. You should define a segment first
and then put your procedure inside it. For example, if you want your function
to be in a pageable segment, you should define a pageable segment first,
like this:</font></font></font>
<blockquote><b><font face="Arial,Helvetica"><font color="#FFCC33"><font size=-1>VxD_PAGEABLE_CODE_SEG</font></font></font></b>
<p><b><font face="Arial,Helvetica"><font color="#66FF99"><font size=-1>[Your
procedure here]</font></font></font></b>
<p><b><font face="Arial,Helvetica"><font color="#FFCC33"><font size=-1>VxD_PAGEABLE_CODE_ENDS</font></font></font></b></blockquote>
<font face="Arial,Helvetica"><font size=-1>You can put many procedures
inside a segment. You as the VxD writer must decide in which segment you
should put your procedures. If your procedures must be in memory at all
time such as hardware interrupt handlers, put them in a locked segment.
Otherwise you should put them in the pageable segment.</font></font>
<br><font face="Arial,Helvetica"><font size=-1>You define your procedure
with <b><font color="#FFFF99">BeginProc</font></b> and <b><font color="#FFFF99">EndProc</font></b>
macros.</font></font>
<blockquote><font face="Arial,Helvetica"><font size=-1><b><font color="#FFCC33">BeginProc
</font></b><i>name</i></font></font>
<p><font face="Arial,Helvetica"><font size=-1><b><font color="#FFCC33">EndProc
</font></b><i>name</i></font></font></blockquote>
<font face="Arial,Helvetica"><font size=-1><b><font color="#FFFF99">name</font></b>
is the name of your procedure. <b><font color="#FFFF99">BeginProc</font></b>
macro can take several more parameters, you should consult Win95 DDK documentation
for detail. But most of the time, you can get by with only the name of
the procedure.</font></font>
<br><font face="Arial,Helvetica"><font size=-1>You should use <b><font color="#FFFF99">BeginProc-EndProc
</font></b>macros
instead of the normal <b><font color="#FFFF99">proc-endp</font></b> directives
because <b><font color="#FFFF99">BeginProc-EndProc</font></b> macros provide
more functionality than <b><font color="#FFFF99">proc-endp</font></b>.</font></font>
<h3>
<font face="Arial,Helvetica"><font color="#66FFFF"><font size=+0>VxD Coding
Convention</font></font></font></h3>
<h3>
<font face="Arial,Helvetica"><font color="#66FF99"><font size=-1>Register
Usage</font></font></font></h3>
<font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>Your VxD
can use any general register, FS and GS. But you should beware about modifying
segment registers. Especially, you should definitely not alter CS and SS
unless you are quite positive you know what you're doing. You can use DS
and ES so long as you remember to restore their values when you return.
Two flags are especially important: direction and interrupt flags. You
should not disable interrupts for an extended period of time and if you
modify the direction flag, don't forget to restore its previous state before
you return.</font></font></font>
<h3>
<font face="Arial,Helvetica"><font color="#66FF99"><font size=-1>Parameter-passing
Convention</font></font></font></h3>
<font face="Arial,Helvetica"><font size=-1><font color="#FFFFFF">There
are two calling conventions for VxD services: register-based and stack-based.
With register-based services, you pass parameters to the services via various
registers and you can check the carry flag after calling the service to
see if the operation is successful. You can not assume that the values
in the general registers will be preserved after calling the services.
With stack-based services, you push the parameters on the stack and you
got the return value in eax. Stack-based services preserve ebx, esi, edi
and ebp. Most of the register-based services originate from Windows 3.x
days. Most of the time, you can differentiate between those two kinds of
services by looking at the names. If the name of the service begins with
an underscore like </font><b><font color="#FFFF99">_HeapAllocate</font></b><font color="#FFFFFF">,
it's a stack-based (C) service (except for a few services exported by </font><b><font color="#FFFF99">VWIN32.VXD</font></b><font color="#FFFFFF">).
If the service name doesn't begin with an underscore, it's a register-based
service.</font></font></font>
<h3>
<font face="Arial,Helvetica"><font color="#66FF99"><font size=-1>Calling
VxD Services</font></font></font></h3>
<font face="Arial,Helvetica"><font size=-1><font color="#FFFFFF">You call
VMM and VxD services by using </font><b><font color="#FFFF99">VMMCall</font></b><font color="#FFFFFF">
and </font><b><font color="#FFFF99">VxDCall </font></b><font color="#FFFFFF">macros.
Both macros have exactly the same syntax. You use </font><b><font color="#FFFF99">VMMCall</font></b><font color="#FFFFFF">
when you want to call VxD services exported by VMM and you use </font><b><font color="#FFFF99">VxDCall</font></b><font color="#FFFFFF">
when you call services exported by VxDs other than the VMM.</font></font></font>
<blockquote><font face="Arial,Helvetica"><font size=-1><b><font color="#FFFF99">VMMCall</font></b><font color="#FFFFFF">
</font><b><font color="#66FF99">service</font></b><font color="#FFFFFF">
; for calling register-based service</font></font></font>
<br><font face="Arial,Helvetica"><font size=-1><b><font color="#FFFF99">VMMCall </font><font color="#66FF99">
_service, <argument list></font></b><font color="#FFFFFF">
; for calling stack-based service</font></font></font></blockquote>
<font face="Arial,Helvetica"><font size=-1><b><font color="#FFFF99">VMMCall</font></b><font color="#FFFFFF">
and </font><b><font color="#FFFF99">VxDCall</font></b><font color="#FFFFFF">
decompose to int 20h followed by a dword that I described in the previous
tutorial but they are much more convenient to use. In the case of stack-based
services, you must enclose the argument list with a pair of angle bracket.</font></font></font>
<blockquote><b><font face="Arial,Helvetica"><font size=-1><font color="#FFFF99">VMMCall </font><font color="#FFFFFF">
_HeapAllocate, </font><font color="#66FF99"><<size mybuffer>, HeapLockedIfDP></font></font></font></b></blockquote>
<font face="Arial,Helvetica"><font size=-1><b><font color="#FFFF99">_HeapAllocate</font></b><font color="#FFFFFF">
is a stack-based service. It accepts two parameters. We must enclose them
inside an angle bracket. However, the first parameter is an expression
that the macro may interpret incorrectly, so we put it inside another angle
bracket.</font></font></font>
<h3>
<font face="Arial,Helvetica"><font color="#66FF99"><font size=-1>Flat Addresses</font></font></font></h3>
<font face="Arial,Helvetica"><font size=-1><font color="#FFFFFF">In older
tools, the assembler and linker generate incorrect addresses when you use
</font><b><font color="#FFFF99">offset
</font></b><font color="#FFFFFF">operator.
So VxD programmers use </font><b><font color="#FFFF99">offset flat:</font></b><font color="#FFFFFF">
instead of </font><b><font color="#FFFF99">offset</font></b><font color="#FFFFFF">.
vmm.inc contains a macro to make it easier. </font><b><font color="#FFFF99">OFFSET32
</font></b><font color="#FFFFFF">expands
to </font><b><font color="#FFFF99">offset flat:</font></b><font color="#FFFFFF">.
So if you want to use offset operator, you should use </font><b><font color="#FFFF99">OFFSET32</font></b><font color="#FFFFFF">
instead.</font></font></font><font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1></font></font></font>
<p><font face="Arial,Helvetica"><font size=-1><b><font color="#66FFFF">Note:</font></b><font color="#FFFFFF">
I experimented with</font><b><font color="#FFFF99"> offset</font></b><font color="#FFFFFF">
operator when I wrote this tutorial. It generated correct addresses so
I think the bug has been removed in MASM 6.14. But just to play safe, you
should use </font><b><font color="#FFFF99">OFFSET32</font></b><font color="#FFFFFF">
macro instead of the plain </font><b><font color="#FFFF99">offset</font></b><font color="#FFFFFF">.</font></font></font>
<br>
<hr WIDTH="100%">
<center><b>[<a href="http://win32asm.cjb.net">Iczelion's Win32 Assembly
Homepage</a>]</b></center>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -