A DPMI client that provides resident protected mode services (also called a "protected mode TSR") must install itself using Int 31H Functions 0C00H and 0C01H. The protected mode TSR first declares its intent to remain resident by calling Function 0C00H, providing the DPMI host with the code and data descriptors and callback entry points for 16-bit and/or 32-bit protected mode. If the TSR does not wish to provide services in a particular mode, it provides a code descriptor for that mode containing all zero bytes. The protected mode TSR then terminates and stays resident by calling Int 31H Function 0C01H. Note that after this function call, the TSR's original addressing context is destroyed; its LDT and IDT no longer exist, although any extended memory blocks it owned at the time of termination remain allocated.
Whenever another DPMI client in the same virtual machine loads or terminates, the DPMI host will inspect its list of protected mode TSRs. If a particular TSR has indicated that it can execute in the active client's mode, the DPMI host will automatically allocate two LDT descriptors in the active client's context, initialize them to the values specified in the protected mode TSR's original Function 0C00H call, and enter the TSR via a FAR CALL at the offset appropriate to the current mode, passing the following values:
CS | executable selector which maps the same memory as the code descriptor in the Int 31H Function 0C00H data structure for the current mode (16-bit or 32-bit) |
(E)IP | Offset specified in the Int 31H Function 0C00H data structure for the current mode (16-bit or 32-bit) |
DS | read/write data selector which maps the same memory as the data descriptor specified in the Int 31H Function 0C00H data structure for the current mode (16-bit or 32-bit) |
ES | 0 |
FS | 0 |
GS | 0 |
AX | Reason for callback: 0=DPMI client loading, 1=DPMI client terminating |
BX | unique handle for the client within the virtual machine |
When a new DPMI client is loaded and executes the initial switch to protected mode, the appropriate callback procedure in the protected mode TSR will be entered by a FAR CALL with AX=0 before the DPMI host returns to the new program. The TSR may then hook interrupts, create descriptors, or allocate memory blocks in the new client's context prior to the client's access to such protected mode resources. For example, the initialization callback gives the TSR an opportunity to insert itself in the chain of handlers for any arbitrary interrupt or exception. The TSRs are invoked in the order of their installation but are removed in the reverse order. The TSR may also need to construct per-client data structures in its own memory, and can use the value supplied to it in BX as a "handle" for the client. The TSR must exit from the initialization callback with a RETF. Similarly, when a DPMI client terminates using Int 21H Function 4CH or Int 31H Function 0C01H, the TSR's callback procedure will be entered by a FAR CALL with AX=1 before the active client's LDT or IDT has been destroyed. The protected mode TSR can then perform any client termination responsibilities of which the client is unaware (e.g. unmapping of physical memory), release any protected mode resources which it has acquired on behalf of the client (e.g. ownership of shared memory), and deallocate any per-client data structures of its own. The termination callback must exit with a RETF and indicate an action to the DPMI host as follows:
Int 31H Functions 0C00H and 0C01H should only be used by DPMI clients which intend to provide resident services to other protected mode clients. If the objective is only to provide resident services to real mode programs, the client should use the DPMI translation service Int 31H Function 0300H to invoke DOS's Int 31H Function 31H directly.