VXD routine: message box
In the previous section, we told the method of writing a VXD program. Now we have to learn to use it. In this section, we have to write a static VXD that pops up a message box when you create or destroy a virtual machine. Download example here.
Capture virtual machine creation and end events
When a virtual machine is created, the VMM sends a CREATE_VM control message to all VXD programs. When a virtual machine exits, it also sends VM_TERMINATE and VM_TERMINATE2 messages to all VXD programs. Our work is very simple: handling create_vm and vm_terminate22 messages in the device control program. When our VXD programs receive these two control messages, it pops up a message box on the screen. When the VXD program receives a CREATE_VM or VM_TERMINATE2 message, the hypothered handle is saved in EBX. A virtual handle can be seen as the only ID of it. Every virtual machine has its own unique ID (virtual machine handle). You can use the virtual machine ID as using the process ID: When calling a function, use it as a parameter transmission. Further, a virtual machine handle is actually a 32-bit linear address that points to the virtual machine control block (VMCB). A virtual machine control block is a structure that includes many important properties about the virtual machine. It is defined as follows:
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 some flag bits that reflect virtual machine status. CB_High_LINEAR is a linear address to a virtual machine mirroring in the system shared area (about 3GB). This concept needs to explain it. Under Window95, a VXD cannot access the V86 area directly, instead, VMM maps each virtual machine's V86 area to the system sharing area. When a VXD program is to access or modify the V86 area in the virtual machine, it operates at a high linear area of the virtual machine. For example, if the displayed address is 0B8000H, your VXD program is to access this area. It is necessary to put the value in CB_High_Linear 0B8000H and then access the area. The modifications you are in a high linear mirror area are saved to the virtual machine because the two areas shared a page directory entry. Using a high linear image is very effective in most cases, because you can even modify a virtual machine that is not the current virtual machine. The CB_Client_Pointer contains the address of the client register structure. A client register structure contains the value of all registers of the V86 or the protection mode program in a virtual machine. If your VXD program is to read / change the status of the V86 or PM program, it can change the value in the client register structure. When the VMM returns the execution of the program, these changes will be saved to the program. CB_VMID Virtual Machine Authentication Number. When the VMM creates a virtual machine, the virtual machine assigns a number. The VMID of the system virtual machine is 1. CB_SIGNATURE contains a string "VMCB". This element is used to detect if the virtual machine handle is valid.
Show a dialog
A VXD program can communicate with users through the Virtual Shell DEVICE service. In this example we have to use one of them: shell_message. Shell_Message is a service function of a register method, transmitting parameters by register:
EBX shows the handle of the virtual machine of this message. The flag of the EAX message box. You can check their details in Shell.inc, they all start with MB_. The 32-bit linear address of the message to which ECX is displayed. The 32-bit linear address of the title of the EDI message box. ESI If you have to know the response operation of the user for your message frame, you will fill out the 32-bit linear address of the return function. If you don't want to know, use NULL. EDX is used to transfer the parameters required for your return function (if you fill in the address of this function in ESI). After returning, if the call is successful, the return flag is cleared, otherwise, the returns are set.
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, ONVMCREATE CONTROL_DISPATCH VM_TERMINATE2, ONVMCLOSE END_CONTROL_DISPATCH MESSAGE
This VXD program handles two control messages, CREATE_VM, and VM_TERMINATE2 When receiving the CREATE_VM control message, it calls the ONVMCREATE function. When a VM_TERMINATE2 message is received, it calls the ONVMCLOSE function.
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
We put these data inside the adjustable page.
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 we BeginProc and EndProc macros to create OnVMCreate. The ONVMCREATE function puts the parameters you need to call the Shell_Message service to the register. Because we want to display the message box on the system virtual machine, you cannot use the value in EBX (EBX contains the handle of the virtual machine created, and we want the handle of the system virtual machine). Thus, we use another VMM service, get_sys_vm_handle to get the virtual machine handle of the system virtual machine. We put the addresses of the address and message box title respectively in ECX and EDI. We don't need to know the customer's response, so we set ESI and EDX to zero. When each parameter is within the corresponding register, we call Shell_Message to display the message box.
Beginproc ONVMCLOSE MOV ECX, Offset32 VMDestroyed JMP Commoncode Endproc ONVMCLOSE
The ONVMCLOSEONVMCLOSE function itself is very simple. Because it is the same as the code to be used, it is turned to the code in ONVMCREATE after initializing ECX with the address of another message.
Change the definition file (.def)
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
Assembly process:
ml -coff -c -cx -dmasm6 -dbld_coff -dis_32 message.asm
Link -vxd -def: message.def message.obj
Vxd installation: put the message.vxd in the / system directory. Plus the following line in the [386ENH] section in the System.ini file: device = message.vxd
Restart your computer. Test this VXD: Open a DOS window, you will see the pop-up message box, display "a VM is created.". When you close a DOS window, a message box will pop up display "a vm is destroyed".