Q67845: Calling a DLL Written for Windows from a TSR for MS-DOS
Article: Q67845
Product(s): Microsoft Windows Device Driver Kit
Version(s): 3.0,3.1
Operating System(s):
Keyword(s):
Last Modified: 03-NOV-1999
-------------------------------------------------------------------------------
The information in this article applies to:
- Microsoft Windows Device Development Kit (DDK) for Windows, versions 3.0, 3.1
-------------------------------------------------------------------------------
SUMMARY
=======
A TSR (terminate-and-stay-resident) program running under MS-DOS can call a
dynamic-link library (DLL) written for the Microsoft Windows environment. This
is possible by using the Interrupt 2Fh services provided by Windows and the
MS-DOS Protected Mode Interface (DPMI).
MORE INFORMATION
================
To call the TSR program, an application can use the DPMI Simulate Real Mode
Interrupt function or the DPMI Call Real Mode Procedure function with a FAR
return frame.
To call a DLL from a TSR, perform the following four steps:
1. Design the function to be called from the TSR similar to an interrupt service
routine (ISR), and put it into a DLL. The module definition (DEF) file for
the DLL must contain the statement CODE PRELOAD FIXED. Here is a code
fragment for a callback function:
; My callback code in a CODE PRELOAD FIXED Windows DLL
;
; Note: The real mode CS:IP in the real mode CallStruct must
; be fixed up for IRET to work correctly, as shown below:
My_Call_Back: ; The real mode callback entry
;==========================================================
; On entry to this routine:
;
; DS:SI -> Real mode SS:SP
; ES:DI -> Real mode call structure
; Interrupts disabled
;
; On exit:
; ES:DI -> Real mode call structure
;==========================================================
call Do_It ; Function that handles
; the callback
cld
lodsw ; Get real mode IP from stack
mov WORD PTR es:[di+2Ah], ax ; Store IP in call struc
lodsw ; Get real mode CS from stack
mov WORD PTR es:[di+2Ch], ax ; Store CS in call struc
add WORD PTR es:[di+2Eh], 4 ; Bump real mode SP past CS:IP
iret ; Exit My_Call_Back
2. Use the DPMI Allocate Real Mode callback function to set up a callback
address to the function, as follows:
mov ax, 0303h ; Allocate real mode callback
; address
push ds
push cs
pop ds
mov si, OFFSET My_Call_Back
pop es
mov di, OFFSET MyRMCS ; Offset of real mode call
; structure, used for DPMI
; translation services
; (see Chapter 11 of the
; INTEL DPMI Spec. v 0.9)
int 31h ; Call DPMI
jc CB_Error ; If carry set, call failed
jmp Set_CB_Addr
CB_Error:
mov ax, 1
jmp Set_CB_Exit
Set_CB_Addr:
mov WORD PTR CB_Addr+2, cx ; Store SEG:OFF of callback
mov WORD PTR CB_Addr, dx ; address in local variable
Set_CB_Exit : ; Exit
3. Pass the real mode callback address, returned from the code above, to the TSR
and store it, as follows:
; Call the TSR, passing the real mode callback in BX:CX
Notify_TSR:
mov bx, WORD PTR CB_Addr+2 ; Real mode callback seg
mov cx, WORD PTR CB_Addr ; Real mode callback off
mov ax, 8F00h ; ID and function number
int TSR_Int_No
cmp al, 00h
jz Notify_Success
Notify_Failure:
mov al, 1 ; Return failure in AL
Notify_Success:
4. When it is time for the TSR to call the DLL, use Interrupt 2Fh to determine
whether the current virtual machine (VM) is VM 1 (the Windows VM). If it is,
use the assembly language statement CALL DWORD PTR dwCallBackAddr to call the
real mode callback address. If the current VM is not VM 1, use the Interrupt
2Fh service Switch VMs and Callback (Function 1685h). Specify the real mode
callback address stored in the TSR in step 3 above for the ES:BX value in the
call.
;
; Code in TSR, which is loaded before Windows
;
Call_DLL_Entry:
mov ax, 1683h ; Windows Interrupt 2Fh
int 2Fh ; (Get Current VM)
cmp bx, 1 ; Windows is always VM 1
; (version 3.0 *ONLY*)
jz Call_DLL ; We're in Windows VM
Switch_VMs_And_Call_DLL: ; We're not in Windows VM
mov ax, 1685h ; Windows Interrupt 2Fh
; switch VMs and callback
mov bx, 1 ; Windows 3.0 is always VM 1
mov cx, 0 ; All flags off
mov dx, 0 ; Priority boost not required
mov si, 0 ;
mov di, seg SwitchProc ; Segment of switch procedure
mov es, di ;
mov di, offset SwitchProc ; Offset of switch procedure
int 2Fh ;
jnc My_1685h_Success
My_1685h_Error:
; AX = error code: 1 = Invalid VM ID
; 2 = Invalid priority boost
; 3 = Invalid flags
.
.
.
jmp Call_DLL_Exit
My_1685h_Success:
mov ax, 0
jmp Call_DLL_Exit
Call_DLL:
Call DWORD PTR CB_Addr ; FAR CALL to real mode
; callback
Call_DLL_Exit:
.
.
.
iret ; return to caller or
; hardware interrupt
SwitchProc proc
pusha
push ds
push es
call DWORD PTR CB_Addr ; FAR CALL to real mode
; callback
pop es
pop ds
popa
iret ; Switches back to VM from
; which it was called
SwitchProc endp
The four steps above allocate a unique procedure callback address and pass it to
the TSR, which stores the address. When the TSR calls the DLL, if the Windows
virtual machine (VM) is running, the TSR calls the callback address directly.
Otherwise, the TSR calls the Switch VMs and Callback function to schedule the
Windows virtual machine. One parameter for this function is the address to call
once the requested VM is running.
In this case, the Windows scheduler switches VMs, then it calls the SwitchProc
function in the TSR. When SwitchProc calls the routine in the DLL that
corresponds to the allocated real mode callback address, the DLL receives
control to perform its processing.
Once the DLL completes its processing, it executes an IRET instruction to return
control to the SwitchProc. Then SwitchProc itself executes an IRET instruction.
At this point, the Windows scheduler switches back to the VM from which it was
called.
All Interrupt 2Fh functions are documented in Appendix C of the "Microsoft
Windows Device Driver Kit: Device Driver Adaptation Guide" for Windows 3.1 and
in Appendix D of the "Microsoft Windows Device Development Kit Virtual Device
Adaptation Guide" for Windows 3.0.
DPMI (Interrupt 31h) services are documented in the Intel document "MS-DOS
Protected Mode Interface Specification." A paper copy of the DPMI specification
is available free of charge from Intel Literature. In the United States, contact
Intel at (800) 548-4725. Outside the US, contact the Intel distributor for your
country.
Additional query words: 3.00 3.10 DDKDPMI DDKTSR
======================================================================
Keywords :
Technology : kbAudDeveloper kbWin3xSearch kbWinDDKSearch kbWinDDK300 kbWinDDK310
Version : :3.0,3.1
=============================================================================
THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.
Copyright Microsoft Corporation 1986-2002.