API translation is required for any V86-mode API function that takes a pointer as a parameter; functions that take no parameters or receive value parameters need no translation. By default, Windows reflects interrupts into V86 mode without translation, so functions that need translation must be intercepted by a virtual device. For example, the virtual MS-DOS manager intercepts Interrupt 21h to translate for calls to MS-DOS system functions such as Read File or Device and Load and Execute Program.
Most virtual devices use the V86MMGR_Xlat_API service to translate function parameters. If a function takes a pointer, this service changes the pointer to an address in the translation copy buffer (in the V86 address space), and copies the corresponding data to that address.
Unfortunately, some API functions are too complex to be translated by the V86MMGR_Xlat_API service. For example, the service cannot translate functions that take pointers to structures that contain more pointers. In such cases, the virtual device must provide custom translations to convert all pointers and copy all corresponding data. Another example is a function that uses a buffer that is larger than the current translation copy buffer. The virtual device can customize the translation by dividing the call into several operations using a smaller buffer.
A virtual device that translates calls to API functions must install a protected-mode interrupt handler to carry out the translations. The interrupt handler must be the last handler in the protected-mode interrupt chain, therefore the virtual device must install it using the Set_PM_Int_Vector service when processing either the Sys_Critical_Init or Device_Init message. The handler must be fully initialized before the system begins sending the Init_Complete message. This allows virtual devices to use the Exec_VxD_Int service while processing the message. None of the V86MMGR translation services, except for V86MMGR_Set_Mapping_Info, should be called during the Sys_Critical_Init or Device_Init messages. Only one virtual device should translate a given API function call.
In many cases, a virtual device combines use of the V86MMGR_Xlat_API service with custom translations. The virtual device typically uses the Xlat_API_Jmp_To_Proc macro with the service to identify functions that need custom translation.
Virtual devices must adjust V86 segment registers when translating functions. To do so, a virtual device can modify the alternate client registers (such as Client_Alt_DS) when the virtual machine status is executing in protected-mode (the CB_VM_Status field in the control block specifies VMStat_Pm_Exec). When in protected-mode, these registers contain the V86 segment registers and stack pointer. They will contain the protected-mode segment registers and stack pointer when the virtual machine is in V86-mode execution.