;       SCCSID = @(#)cfix.asm	6.2 91/05/13
; ****************************************************************************
; *                                                                          *
; *                       IBM/Microsoft Confidential                         *
; *                                                                          *
; *                 Copyright (c) IBM Corporation  1987, 1990                *
; *                 Copyright (c) Microsoft Corp.  1987, 1990                *
; *                           All Rights Reserved                            *
; *                                                                          *
; ****************************************************************************
;*********************** START OF SPECIFICATIONS *********************
;
;   SOURCE FILE NAME: cfix.asm
;
;   DESCRIPTIVE NAME: necessarry assembler interfaces for LogCalls APIs
;
;   COPYRIGHT: (TOP MODULE ONLY)
;
;   STATUS: RELEASE 1 LEVEL 0
;
;   FUNCTION:
;
;   NOTES:
;      The code in this module is closely tied to the C runtime
;      environment. Use of these routines must be cautious since
;      different routines assume the state of the stack is correct
;      for them to be called.
;
;   ENTRY POINTS:
;                       ENTER_DLL          (CODE16  segment)
;                       EXIT_DLL           (CODE16  segment)
;                       ENTER_DLL_CONFORM  (CODE16C segment)
;                       EXIT_DLL_CONFORM   (CODE16C segment)
;
;   INTERNAL REFERENCES:  none
;
;   EXTERNAL REFERENCES:  none
;
;************************ END OF SPECIFICATIONS *************************

.286p

include struc.inc
include basemaca.inc
include dc1segs.inc                                             ; DCR 704

CODE16    SEGMENT                                               ; DCR 704
CODE16    ENDS

CODE16C   SEGMENT
CODE16C   ENDS

;
;       Definitions for interfaces to C Data.  We also gather all of this
;       data into the instance data area.  The C compiler will emit
;       the following three segments when directing the data to a different
;       segment

        ASSUME  CS: CODE16 , DS: DATA16                         ; DCR 704

DATA16  SEGMENT

        public  __acrtused
__acrtused equ  1               ; C compiler puts out an extern

DATA16  ENDS

CODE16  SEGMENT


;*********************** START OF SPECIFICATIONS **************************
;
;   SUBROUTINE NAME: ENTER_DLL
;
;   DESCRIPTIVE NAME: enter DLL  (Push All, Set DS)
;
;   FUNCTION: Pushes all registers which may be corrupted by C,sets
;             DS to the DATA16       of the DLL
;
;   NOTES: Glue For Entering a DLL coded in C. This must be the first
;          thing called from a DLL API implemented in C to save the
;          requestor's environment.
;
;          This routine should only be called from the CODE16 segment
;
;          This MUST BE DECLARED AS: extern pascal ENTER_DLL()
;
;          C Calling Convention: ENTER_DLL();
;
;   ENTRY POINT: ENTER_DLL
;
;   INPUT:              none
;
;   EXIT-NORMAL:        N/A
;
;   EXIT-ERROR:         N/A
;
;   EFFECTS:    "pops" return address off stack, saves BX,CX,DX,
;               DS, and ES, pushes return address back onto stack,
;               set DS = to DATA16      , and returns; AX is corrupted
;
;   INTERNAL REFERENCES:    none
;
;   EXTERNAL REFERENCES:    none
;
;************************ END OF SPECIFICATIONS **************************

Procedure ENTER_DLL

    pop     ax                      ; Save RetIP

    push    0                       ; Push Dummy For EXIT_DLL

    push    ds                      ; Save Registers
    push    es
    push    bx
    push    cx
    push    dx
    push    si
    push    di

    mov     dx, DATA16              ; move DATA16                       DCR 704
    mov     ds, dx                  ;  into DS

assume ds:DATA16                                                      ; DCR 704

    jmp     ax                      ; Ret

EndProc ENTER_DLL


;*********************** START OF SPECIFICATIONS ***************************
;
;   SUBROUTINE NAME: EXIT_DLL
;
;   DESCRIPTIVE NAME: Exit DLL (Pop All registers)
;
;   FUNCTION: Pops all registers which were saved to prevent
;             corruption by C code
;
;   NOTES: Glue For Exiting a DLL coded in C. This must be the last
;          thing coded in a DLL API implemented in C to restore the
;          requestor's environment.
;
;          This routine should only be called from the CODE16 segment
;
;          This MUST BE DECLARED AS: extern pascal EXIT_DLL(unsigned int)
;
;          C Calling Convention: EXIT_DLL(API RC);
;
;   ENTRY POINT: EXIT_DLL
;
;   INPUT:      DW      return code
;
;   EXIT-NORMAL:        N/A
;
;   EXIT-ERROR:         N/A
;
;   EFFECTS:    reverses the effects of ENTER_DLL/EXIT_DLL
;               pops the return address off the stack, exchanges
;               with the indicated old registers on stack, sets
;               AX to the return code and restores the remaining
;               registers
;
;   INTERNAL REFERENCES:    none
;
;   EXTERNAL REFERENCES:    none
;
;************************ END OF SPECIFICATIONS ****************************

Procedure EXIT_DLL

    pop     bx              ; Save RetIP
    pop     ax              ; (ax) is now restored correctly

    push    bp
    mov     bp, sp

    mov     [bp+16], bx     ; Save RetIP in Dummy Storage from ENTER_DLL
    pop     bp

    pop     di              ;restore
    pop     si              ;  register
    pop     dx              ;    set
    pop     cx              ;
    pop     bx              ;
    pop     es              ;
    pop     ds              ;

    ret                     ; return

EndProc EXIT_DLL
                            ;restore
CODE16     ENDS               ;  register
                            ;    set

        ASSUME  CS: CODE16C , DS: DATA16
CODE16C SEGMENT


;*********************** START OF SPECIFICATIONS **************************
;
;   SUBROUTINE NAME: ENTER_DLL_CONFORM
;
;   DESCRIPTIVE NAME: enter DLL  (Push All, Set DS)
;
;   FUNCTION: Pushes all registers which may be corrupted by C,sets
;             DS to the DATA16       of the DLL
;
;   NOTES: Glue For Entering a DLL coded in C. This must be the first
;          thing called from a DLL API implemented in C to save the
;          requestor's environment.
;
;          This routine should only be called from the CODE16C segment
;
;          This MUST BE DECLARED AS: extern pascal ENTER_DLL_CONFORM()
;
;          C Calling Convention: ENTER_DLL_CONFORM();
;
;   ENTRY POINT: ENTER_DLL_CONFORM
;
;   INPUT:              none
;
;   EXIT-NORMAL:        N/A
;
;   EXIT-ERROR:         N/A
;
;   EFFECTS:    "pops" return address off stack, saves BX,CX,DX,
;               DS, and ES, pushes return address back onto stack,
;               set DS = to DATA16      , and returns; AX is corrupted
;
;   INTERNAL REFERENCES:    none
;
;   EXTERNAL REFERENCES:    none
;
;************************ END OF SPECIFICATIONS **************************

Procedure ENTER_DLL_CONFORM

    pop     ax                      ; Save RetIP

    push    0                       ; Push Dummy For EXIT_DLL_CONFORM

    push    ds                      ; Save Registers
    push    es
    push    bx
    push    cx
    push    dx
    push    si
    push    di

    mov     dx, DATA16              ; move DATA16
    mov     ds, dx                  ;  into DS

assume ds:DATA16

    jmp     ax                      ; Ret

EndProc ENTER_DLL_CONFORM


;*********************** START OF SPECIFICATIONS ***************************
;
;   SUBROUTINE NAME: EXIT_DLL_CONFORM
;
;   DESCRIPTIVE NAME: Exit DLL (Pop All registers)
;
;   FUNCTION: Pops all registers which were saved to prevent
;             corruption by C code
;
;   NOTES: Glue For Exiting a DLL coded in C. This must be the last
;          thing coded in a DLL API implemented in C to restore the
;          requestor's environment.
;
;          This routine should only be called from the CODE16C segment
;
;        This MUST BE DECLARED AS: extern pascal EXIT_DLL_CONFORM(unsigned int)
;
;          C Calling Convention: EXIT_DLL_CONFORM(API RC);
;
;   ENTRY POINT: EXIT_DLL_CONFORM
;
;   INPUT:      DW      return code
;
;   EXIT-NORMAL:        N/A
;
;   EXIT-ERROR:         N/A
;
;   EFFECTS:    reverses the effects of ENTER_DLL_CONFORM/EXIT_DLL_CONFORM
;               pops the return address off the stack, exchanges
;               with the indicated old registers on stack, sets
;               AX to the return code and restores the remaining
;               registers
;
;   INTERNAL REFERENCES:    none
;
;   EXTERNAL REFERENCES:    none
;
;************************ END OF SPECIFICATIONS ****************************

Procedure EXIT_DLL_CONFORM

    pop     bx              ; Save RetIP
    pop     ax              ; (ax) is now restored correctly

    push    bp
    mov     bp, sp

    mov     [bp+16], bx    ; Save RetIP in Dummy Storage from ENTER_DLL_CONFORM
    pop     bp

    pop     di              ;restore
    pop     si              ;  register
    pop     dx              ;    set
    pop     cx              ;
    pop     bx              ;
    pop     es              ;
    pop     ds              ;

    ret                     ; return

EndProc EXIT_DLL_CONFORM
                            ;restore
CODE16C    ENDS               ;  register
                            ;    set
        END                 ;
