include vmm.inc
push dword ptr Interrupt
VMMCall Exec_VxD_Int
Executes the specified software interrupt. Virtual devices use this service to call MS-DOS or BIOS functions outside the context of a nested execution block.
Before calling this service, a virtual device must set registers to values that are appropriate for the specified software interrupt. This service supports all MS-DOS and BIOS functions that are supported in protected-mode programs.
This service does not change the client registers and flags, so there is no need for the virtual device to save and restore the client register structure. This service also pops the interrupt number from the stack.
Interrupts will only be routed through virtual device interrupt hooks. They will bypass any hook the application has installed in protected mode. This may be a problem, for example, if an application hooks Int 21h to watch file opens and then a VxD uses this service to open a file (the application would not see the file open). DO NOT CHANGE DS or ES before calling this service. You should always use the ring 0 linear address of the data instead of changing the selector value. This may require using the _SelectorMapFlat service to determine the base of a selector.
Do not call services that will change DS or ES.. Mappers should return valid pointers without changing the segment register value, but calls that explicitly change the DS or ES selectors should never be called. For example, if a call returns a pointer in DS:(E)DX then this would be OK to call since the mapper would convert the ponter to use the ring 0 linear address in EDX without modifying DS. However, if a service returns a selector only then you should not use Exec_VxD_Int to call it. This can normally be made to work by using code similar to the following:
Push_Client_State
VMMcall Begin_Nest_(V86_)Exec
. . .
(Fiddle with client registers)
. . .
VMMcall Exec_Int
. . .
(Get segments/selectors)
. . .
VMMcall End_Nest_Exec
Pop_Client_State
Upon exit, all registers and flags modified by interrupt will be changed. The interrupt number on the stack will have been removed. If called within a must complete section and a fatal error occurred while executing the interrupt the carry flag will be set.
In Windows 3.1, if you called Exec_VxD_Int at a time when there was no protected-mode app in the VM and if someone then did a Begin_Nest_Exec (not Begin_Nest_V86_Exec), the system VM would crash. This problem has been corrected in Windows 95.
The following examples calls the MS-DOS function Get Version (Interrupt 21h, Function 30h):
mov ax, 3000h
push dword ptr 21h
VMMCall Exec_VxD_Int
mov [Major], al ; major MS-DOS version
mov [Minor], ah ; minor MS-DOS version