VXD EXAMPLE: MESSAGEBOX
In the previous tutorials, you learn about mechanics of VxD programming. Now is the time to apply what you have learned. In this tutorial, we will create a simple static VxD which will display a message box whenever a VM is created / destroyed.
Trapping VM CREATION AND TERMINATION EVENTS
When a VM is created, the VMM sends Create_VM control message to all VxDs Also when a VM is terminated normally, it sends VM_Terminate and VM_Terminate2 to all VxDs Our job is easy:.. Process Create_VM and VM_Terminate2 messages in our device control procedure When. Our Vxd Receives Those Two Control Messages, It Displays a Message Box on the screen.
When our VxD receives Create_VM or VM_Terminate2 message, ebx contains the handle of the VM. A VM handle can be considered as the unique ID of the VM. Each VM has its unique ID (VM handle). You can use VM handle in the same Manner as you use a process ID, by passing it as a parameter to the service That Need IT.
On Closer Examination, A VM Handle Is Actually The 32-Bit Linear Address of The VM Control Block (VMCB).
VM Control Block Is A Structure That Contains Several Important Items About The Vm. It's defined as:
CB_S STRUC
CB_VM_STATUS DD?
CB_HIGH_LINEAR DD?
CB_CLIENT_POINTER DD?
CB_VMID DD?
CB_SIGNATURE DD?
CB_S ENDS
CB_VM_Status contains the bit flags that you can examine to find out about the state of the VM. CB_High_Linear is the starting linear address of the mirror of the VM in the shared system region (above 3 GB). This concept requires an explanation. Under Windows 95, a VxD should not touch the V86 region directly instead the VMM maps the whole V86 region of every VM to the shared system region. When a VxD wants to modify / touch the memory in V86 region of the VM, it should do so to the high-linear area of the VM. For example, if the video memory is at 0B8000h and your VxD needs to touch that area, it should add the value in CB_High_Linear to 0B8000h and touch that area instead. The changes you made to the high -linear mirror will be reflected to the VM because both areas share the same page directory entry. Using the high-linear mirror is better in most situation because you can modify the VM even if it's not the current VM. CB_Client_Pointer contains the address of the Client Register Str ucture. The client register structure contains the values of all registers of the interrupted V86 or protected mode application in the VM. If your VxD wants to know / modify the state of the V86 or PM application, it can modify the members of the client register structure and the changes will propagate to the application when the VMM resumes its execution. CB_VMID The numeric identifer of the VM. The VMM assigns this number when it creates the VM. The system VM has the VMID of 1. CB_Signature contains the string "VMcb "This Member is buy in checking if the vm handle is valid.displaying a messagebox
A VxD can use Virtual Shell Device services to communicate to the users. One such service we will use in this example is SHELL_Message.SHELL_Message is a register-based service. You pass parameters to it via registers.
ebx Handle of the VM that is responsible for the message eax MessageBox flags. You can look them up in shell.inc. They start with MB_. ecx 32-bit linear address of the message to display edi 32-bit linear address of the message box caption esi 32-bit linear address of the callback function in case you need to know the response of the user to the message box. If you do not want to know, use NULL. edx Reference data that will be passed to your callback (if you specify one in ESI)
On Return, The Carry Flag Is Clear If The Call Is Successful. The Carry Flag Is Set Otherwise.
The Example
.386P
Include vmm.inc
INCLUDE shell.inc
DECLARE_VIRTUAL_DEVICE Message, 1,0, Message_Control, undefined_device_id, undefined_init_order
Begin_Control_Dispatch Message Control_Dispatch Create_VM, ONVMCREATE CONTROL_DISPATCH VM_TERMINATE2, ONVMCLOSE END_CONTROL_DISPATCH MESSAGE
Vxd_pageable_data_seg msgtitle DB "Vxd MessageBox", 0 VMCreated DB "a VM IS Created", 0 VMDESTROYED DB "a VM Is Destroyed", 0 vxd_pageable_data_ends
VxD_PAGEABLE_CODE_SEG BeginProc OnVMCreate mov ecx, OFFSET32 VMCreated CommonCode: VMMCall Get_sys_vm_handle mov eax, MB_OK MB_ICONEXCLAMATION mov edi, OFFSET32 MsgTitle xor esi, esi xor edx, edx VxDCall SHELL_Message ret EndProc OnVMCreate
Beginproc ONVMCLOSE MOV ECX, Offset32 VMDESTROYED JMP Commoncode EndProc ONVMCLOSE VXD_PAGEABLE_CODE_ENDS
end
Analysis:
Begin_Control_Dispatch Message
Control_dispatch create_vm, ONVMCREATECONTROL_DISPATCH VM_TERMINATE2, ONVMCLOSE
END_CONTROL_DISPATCH MESSAGE
The VxD processes two control messages, Create_VM and VM_Terminate2. When Create_VM control message is received, it calls OnVMCreate procedure. And when it receives VM_Terminate2 message, it calls OnVMClose procedure.
Vxd_pageable_data_seg
Msgtitle DB "vxd messagebox", 0
Vmcreated DB "a vm is create", 0
Vmdestroyed DB "a vm is destroyed", 0
VXD_PAGEABLE_DATA_ENDS
We Put the data in the pageable data segment.
BeginProc ONVMCREATE
MOV ECX, Offset32 Vmcreated
Commoncode:
VMMCALL GET_SYS_VM_HANDLE
MOV EAX, MB_OK MB_ICONEXCLAMATION
MOV EDI, Offset32 Msgtitle
XOR ESI, ESI
XOR EDX, EDX
Vxdcall shell_message
RET
EndProc ONVMCREATE
OnVMCreate procedure is created using BeginProc and EndProc macros. It puts the parameters for SHELL_Message service into the registers. Since we want to display the message box in the system VM, we can not use the value in ebx (which is the handle of the VM that is being created). Instead, we use a VMM service, Get_Sys_VM_Handle, to obtain the VM handle of the system VM. This service returns the VM handle in ebx. We put the addresses of the message and the caption into ecx and edi, respectively ....................... ..
Beginproc ONVMCLOSE
MOV ECX, Offset32 VMDESTROYED
JMP CommonCode
Endproc ONVMCLOSE
ONVMCLOSEPROCEDURE IS SIMPLICITY INTSELF. Since It Uses Identical Code as ONVMCREATE, IT ITIALIZES ECX with The Address of The Different Message and The Jumps To The Code Inside ONVMCREATE.
Module Definition File
Vxd Message
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' Nondiscard ABLE 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
Message_ddb @ 1
Assembling Process
ml -coff -c -cx -dmasm6 -dbld_coff -dis_32 message.asm
Link -vxd -def: message.def message.objvxd installation
Put Message.vxd In / System Folder Add The Following Line Inside [386ENH] Section of System.ini
Device = message.vxd
Reboot your computer
Testing the vxd
Create a dos box. You will see the message, "a VM is create". When You Close The Dos Box, a Message Box Appears with the message, "a VM is destroyed".
[ICZelion's Win32 Assembly HomePage]