ICZelion Vxd TUT4

zhaozj2021-02-11  244

Vxd Programming: Primer

WE KNOW How To Build A VXD Which Does Nothing. In this Tutorial, We will make it it more productive by adding control message handlers.

Vxd Initialization and Termination

There Are Two Types of Vxd: Static and Dynamic. Each Type Has Different Load Method. They Also Receive Different Initialization and Termination Control Messages.

Static vxd:

VMM loads a static vxd when:

A Real-Mode Resident Programs Issue Int 2FH, 1605H To load it the vxd isot:

HKEY_LOCAL_MACHINE / SYSTEM / CURRENTCONTROLSET / SERVICES / VXD / Key / StaticVxd = Pathname

The vxd is specified in system.ini under [386EN] section:

Device = Pathname

During development period, I suggest you load the VxD from system.ini because if something goes wrong with your VxD to the extent that Windows can not start, you can edit system.ini from DOS. You can not do that with the registry loading method .

When the VMM Loads your static vxd, your vxd will receive Three System Control Messages In The Following Order:

Sys_critical_init vmm Sends this Control Message After Switching Into Protected Mode But Before Enabling Interrupts. Most Vxds Don't Need To Handle this message Except When:

Your VxD hooks some interrupts that will be called later by other VxDs or protected mode programs. Since the interrupts are disabled when you process this control message, you can be sure that the interrupts you're hooking will not be called during the time you 're hooking them. your VxD provides some VxD services that will be called during initialization by other VxDs. For example, some VxD that loads after your VxD may need to call one of your VxD's services during Device_Init control message processing. Since Sys_Critical_Init message is sent before Device_Init message, you must initialize your services during Sys_Critical_Init message If you process this message, you should do your initialization as quickly as possible to prevent hardware interrupt losses due to excessive latency.. (Remember: the interrupts are disabled) Device_Init VMM sends This Control Message After The Interrupts Are Enabled. Most Vxds Perform Initialization In response to this message. Because The Interrupts Are E nabled, time-consuming operations can be done without the fear of losing hardware interrupts. You should do your initialization here (if needed). Init_Complete After all VxDs processed Device_Init message but before the VMM releases all initialization segments (ICODE and RCODE segment classes) , the VMM sends this control message. Few VxDs need to process this message.Your VxD must clear the carry flag if the initialization is successful else you must set the carry flag in case of error before returning. you do not have to process any of the three initialization message if your vxd doesn't nesed anyinitialization.

When It's Time to Terminate The Static VXD, The VMM Sends The Following Control Messages:

System_Exit2 When your VxD receives this message, Windows 95 is about to shut down. All other VMs except the system VM are already destroyed. However the CPU is still in protected mode and it's still safe to execute real-mode code in the system VM. kernel32.dll was already unloaded by this time. Sys_Critical_Exit2 Your VxD receives this message when all VxDs have processed System_Exit2 and the interrupts are disabled.Most VxDs do not need to process those two messages, except when you want to prepare the system to enter real mode. You should know that when Windows 95 shuts down, it enters real mode. So if your VxD did something to the real-mode image that will make it unstable, it should restore the change during this time.

You may wonder why those two exit messages have "2" appended to them.Remember that when the VMM loads the static VxDs, it loads the VxDs with the lower initialization order first so that the VxDs can rely upon services of the VxDs that load before THEM. for Example, IF VXD2 Relies on The Services of Vxd1, IT Must Specify ITS Initialization Order to Be Larger That of vxd1. The load order 10 BE:

..... vxd1 ===> vxd2 ===> vxd3 .....

Now during unloading, it stands to reason that the VxDs that initialize later should uninitialize first so that they may still call VxD services of the VxDs that were loaded before them In the above example, the order should be.:

.... vxd3 ===> vxd2 ===> vxd1 .....

In the above example, if VxD2 called some VxD1's services during initialization, it may need to rely on VxD1's services again during unloading. System_Exit2 and Sys_Critical_Exit2 are sent in reverse initialization order. It means that, when VxD2 receives those messages, VxD1 has not done uninitialization yet and it can still call VxD1's services. System_Exit and Sys_Critical_Exit messages are not sent in reverse initialization order. It means that when you process those two messages, you can not be sure that you can still call VxD's services of the VxDs that Were loaded before you. Those Messages SHOULD NOT BE Used for newer vxds.there Are Two More Exit Messages:

Device_Reboot_Notify2 Notifies the VxD that the VMM is going to restart the system. The interupts are still enabled during this time. Crit_Reboot_Notify2 Notifies the VxD that the VMM is going to restart the system. The interrupts are disabled.

By Now, You Should Be Able To Guess That There Device_reboot_notify and crit_reboot_notify messages But They is the "2" Version.

Dynamic vxd:

Dynamic VxDs can be dynamically loaded and unloaded during Windows 9x sessions. This feature is not available under Windows 3.x. The primary goal of dynamic VxDs is to support dynamic hardware reconfiguration such as Plug and Play devices. However, you can load / unload Them from your Win32 Applications As Well, Making The Ideal As your application 'Ring-0 Extension.

Tutorial is a static vxd. You can communicate The example Into a dynamic vxd by adding the keyword dynamic to the vxd statement in .def file.

Vxd flightvxd Dynamic

That's all you have to do to control a static vxd it Dynamic One.Dynamic vxd can be loading by:

Putting it in / SYSTEM / IOSUBSYS folder in your Windows folder. The VxDs in this folder will be loaded by Input Output Supervisor (IOS). The VxDs in this folder should support layer device drivers so it may not be a good idea to load your dynamic VxD this way. Using VxD Loader service. VxDLDR is a static VxD that can load dynamic VxDs. you can call its services from other VxDs or from 16-bit code. Using CreateFile API from a Win32 application. you specify the dynamic VxD you Want to load to createfile in the format Below:

//./pathname

For example, if you want to load a dynamic vxd named firstvxd Which is in the capital Directory, You Should Do It As Follows: .data vxdname db "//./firstvxd.vxd" 0 .... .data HDEVICE DD? ..... .code ..... Invoke Createfile, Addr VxDName, 0,0,0,0, file_flag_delete_on_close, 0 MOV HDEvice, EAX ... Invoke CloseHandle, HDevice ... ...

File_flag_delete_on_close flag specifies That the vxd is unloadedhen the handle return by createfile isclosed.

If you use CreateFile to load a dynamic VxD, the VxD must handle w32_DeviceIoControl message. VWIN32 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. W32_DeviceIoControl messages Are Also Sent When The Application Calls Deviceiocontrol API to Communicate with the Vxd. We will Examine Deviceiocontrol Interface in The Later Tutorial.

A Dynamic vxd receives One Message During Initialization:

SYS_DYNAMIC_DEVICE_INIT

And One Control Message During Termination:

SYS_DYNAMIC_DEVICE_EXIT

A dynamic VxD will not receive Sys_Critical_Init, Device_Init and Init_Complete 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 That

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..:

CREATE_VM VM_CRITICAL_INIT VM_SUSPEND VM_RESUME CLOSE_VM_NOTIFY DESTROY_VM

IT's Your Responsibility to Choose To Respond to The Control Messages You're Intested in.

Creating procedures inside vxd

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..:

Vxd_pageable_code_seg

[Your Procedure Here]

VXD_PAGEABLE_CODE_ENDS

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.

You Define your procedure with beginproc and endproc macros.

BeginProc Name

EndProc Name

name is the name of your procedure. BeginProc 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.You should use BeginProc-EndProc macros INSTEAD OF THE NORMAL Proc-Endp Directives Because Beginproc-Endproc Macros Provide More FunctionAlity Than Proc-Endp.

Vxd Coding Convertion

Register usage

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, do not forget to restore its Previous State Before You Return.

Parameter-passing convention

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 _HeapAllocate, it's a stack-based (C) service (except for a few services exported by VWIN32.VXD). If the service name does not begin with an underscore, it's a register-based service.Calling VxD Services

You call VMM and VxD services by using VMMCall and VxDCall macros. Both macros have exactly the same syntax. You use VMMCall when you want to call VxD services exported by VMM and you use VxDCall when you call services exported by VxDs other than the VMM.

VMMCall Service; for Calling Register-Based Service

Vmmcall_service, ; for calling stack-based service

VMMCall and VxDCall 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.

Vmmcall_heapallocate, << Size MyBuffer>, Heaplockedifdp>

_HeapAllocate 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.Flat Addresses

In older tools, the assembler and linker generate incorrect addresses when you use offset operator So VxD programmers use offset flat:.. Instead of offset vmm.inc contains a macro to make it easier OFFSET32 expands to offset flat :. So if you want. To Use offset operator, you shouth use offset32 instead.

Note: I experimented with offset 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 OFFSET32 macro instead of the plain offset...

[ICZelion's Win32 Assembly HomePage]

转载请注明原文地址:https://www.9cbs.com/read-4636.html

New Post(0)