; C0NT.ASM - C run time library entry point for NT

;
;       C/C++ Run Time Library - Version 1.5
; 
;       Copyright (c) 1991, 1994 by Borland International
;       All Rights Reserved.
; 

                .386P
ifndef MASM
                model flat
endif
                ASSUME   CS: FLAT, DS: FLAT, SS: FLAT, ES: FLAT

BSSINIT         equ     1       ; Fix for problem with OS not initializing
                                ;  the first page of BSS to zero
FULLBSS         equ     1       ; Fix for problem with OS not initializing
                                ;  the entire BSS to zero

;----------------------------------------------------------------------
; Code segment

_TEXT           SEGMENT PUBLIC DWORD USE32 PUBLIC 'CODE'
_TEXT           ENDS

;----------------------------------------------------------------------
; Data segments

_DATA           SEGMENT PUBLIC DWORD USE32 PUBLIC 'DATA'
                db      'Borland C++ - Copyright 1994 Borland Intl.',0
_DATA           ENDS

_TLSCBA         SEGMENT PUBLIC DWORD USE32 PUBLIC 'TLSCBA'
_TLSCBA         ENDS

_INIT_          SEGMENT PUBLIC WORD USE32 PUBLIC 'INITDATA'
InitStart       label byte
_INIT_          ENDS

_INITEND_       SEGMENT PUBLIC WORD USE32 PUBLIC 'INITDATA'
InitEnd         label byte
_INITEND_       ENDS

_EXIT_          SEGMENT PUBLIC WORD USE32 PUBLIC 'EXITDATA'
ExitStart       label byte
_EXIT_          ENDS

_EXITEND_       SEGMENT PUBLIC WORD USE32 PUBLIC 'EXITDATA'
ExitEnd         label byte
_EXITEND_       ENDS

ifndef MASM
                NOWARN  RES
endif
CONST           SEGMENT PUBLIC DWORD USE32 PUBLIC 'CONST'
CONST           ENDS
ifndef MASM
                WARN    RES
endif

_BSS            SEGMENT PUBLIC DWORD USE32 PUBLIC 'BSS'
IFDEF   BSSINIT
bdata@          label   byte
ENDIF
_BSS            ENDS

IFDEF   BSSINIT
_BSSEND         SEGMENT PUBLIC DWORD USE32 PUBLIC 'BSS'
edata@          label   byte
_BSSEND         ENDS
ENDIF

IFDEF   BSSINIT
DGROUP          GROUP _DATA, _TLSCBA, _INIT_, _INITEND_, _EXIT_, _EXITEND_, CONST, _BSS, _BSSEND
ELSE
DGROUP          GROUP _DATA, _TLSCBA, _INIT_, _INITEND_, _EXIT_, _EXITEND_, CONST, _BSS
ENDIF

;----------------------------------------------------------------------
; External function definitions

_TEXT           SEGMENT PUBLIC DWORD USE32 PUBLIC 'CODE'

ifdef DLL       ; DLL startup

EXTRN           DllEntryPoint:NEAR
EXTRN           __startupd:NEAR
EXTRN           __ErrorMessage:NEAR
EXTRN           GetVersion:NEAR

else            ; EXE startup

ifdef WINDOWS
EXTRN           WinMain:NEAR
else
EXTRN           _main:NEAR
endif

endif

EXTRN           __startup:NEAR
EXTRN           __matherr:NEAR
EXTRN           __matherrl:NEAR

EXTRN           __ExceptInit:NEAR
EXTRN           __GetExceptDLLinfoInternal:NEAR
EXTRN           __DestructorCountPtr:DWORD
EXTRN           GetModuleHandleA:NEAR

_TEXT           ENDS

;----------------------------------------------------------------------
; External data definitions

_DATA           SEGMENT PUBLIC DWORD USE32 'DATA'

ifndef DLL       ; EXE startup
EXTRN           __fmode:NEAR
endif

_DATA           ENDS

;----------------------------------------------------------------------
; CV4 debugging information: a pointer to main, WinMain, or DllEntryPoint

ifndef MASM ; MASM386 can't handle 'dp' directive

$$BSYMS         SEGMENT PUBLIC BYTE USE32 'DEBSYM'
                dd  2       ; magic
                dw  8       ; magic
                dw  210h    ; magic (S_ENTRY32)
ifdef DLL
                dp  DllEntryPoint
else
ifdef WINDOWS
                dp  WinMain
else
                dp  _main
endif
endif
$$BSYMS         ENDS

endif   ; ndef MASM

;----------------------------------------------------------------------
; MODULE_DATA table.
;
; This table contains information about this EXE or DLL that is used
; by startup.c to properly initialize or clean up the module.
; IMPORTANT: the layout must exactly match the MODULE_DATA structure
; definition in startup.c!


_DATA           SEGMENT PUBLIC DWORD USE32 'DATA'

                align   4
module_data     dd      offset FLAT:InitStart
                dd      offset FLAT:InitEnd
                dd      offset FLAT:ExitStart
                dd      offset FLAT:ExitEnd
ifdef WINDOWS
                dd      1                       ; flags
else
                dd      0                       ; flags
endif
                dd      0                       ; module handle
ifdef DLL
                dd      offset FLAT:DllEntryPoint
                dd      0                       ; matherr
                dd      0                       ; matherrl
                dd      0                       ; stack base
                dd      0                       ; fmode
else
ifdef WINDOWS
                dd      offset FLAT:WinMain
else
                dd      offset FLAT:_main
endif
                dd      offset FLAT:__matherr
                dd      offset FLAT:__matherrl
                dd      0                       ; stack base
                dd      offset FLAT:__fmode
endif

public          ___isDLL
ifdef DLL
___isDLL        db      1
else
___isDLL        db      0
endif

public          __TLS_index
__TLS_index     dd      0
public          __TLS_index4
__TLS_index4    dd      0

save_stacktop   dd      0,0


public          ___isGUI
ifdef DLL
___isGUI        db      1
else
ifdef WINDOWS
___isGUI        db      1
else
___isGUI        db      0
endif
endif

public          __hInstance
__hInstance     dd      0  ; Global _hInstance

ifdef DLL
usecount        db      0
nonsharedMsg    db      'Nonshared DATA segment required',0
win32sMsg       db      'Cannot run multiple instances of a DLL under WIN32s',0
endif
_data           ENDS

;----------------------------------------------------------------------
; Startup code

_TEXT           SEGMENT  DWORD USE32 PUBLIC 'CODE'

                public __acrtused
__acrtused      PROC NEAR

                mov     eax, __TLS_index
                shl     eax, 2
                mov     __TLS_index4, eax

ifdef   BSSINIT
ifdef   DLL
                cmp     dword ptr [esp+8], 1    ; Check whether Process Attach
                jne     skipBSSInit
endif
                push    edi
                push    ecx

                xor     eax, eax
                mov     edi, offset DGROUP: bdata@
                mov     ecx, offset DGROUP: edata@
                cmp     ecx, edi
                jna     BSSInitDone
ifdef   FULLBSS
                sub     ecx, edi
else
                mov     ecx, edi
                and     ecx, 0fffh
                jecxz   BSSInitDone
                sub     ecx, 1000h
                neg     ecx
endif
                cld
                rep     stosb
BSSInitDone:
                pop     ecx
                pop     edi
skipBSSInit:
endif

;
;       When an EXE is loaded, all of the statically linked DLL's are
;       initialized before the EXE starts running. That means that we
;       have to make sure to initialize the exception-handling values
;       before we let the DLL initialize itself, since all DLL's use
;       the EXE's exception-handling variables; for this purpose, we
;       call the function _ExceptInit() with a 0 argument whenever a
;       DLL is told that it is being attached to a process. Inside
;       this routine we will call into the EXE to get the addresses
;       of the exception-handling variables. We also call the same
;       function when the EXE itself is initialized.

ifdef DLL
                cmp     dword ptr [esp+8], 1
                jne     not_process_attach
                cmp     usecount, 0
                je      firstInit
                mov     edx, offset nonsharedMsg
                call    GetVersion
                and     eax, 080000000h
                jz      msgSet
                mov     edx, offset win32sMsg
msgSet:
                push    edx
                call    __ErrorMessage
                pop     eax
                xor     eax, eax
                jmp     return
firstInit:
                inc     usecount
endif
                mov     edx, fs:[4]
                mov     eax, [edx-8]
                mov     [save_stacktop  ], eax
                mov     eax, [edx-4]
                mov     [save_stacktop+4], eax
                sub     edx, 4
                mov     [__DestructorCountPtr], edx

ifndef DLL
                sub     edx, 4
                cmp     edx, esp
                jae     stacktop_OK
                mov     esp, edx
stacktop_OK:

endif

                push    0
                call    __ExceptInit
                pop     ecx

not_process_attach:

                push    offset FLAT:module_data
ifdef DLL
                mov     eax, [esp+8]      ; get mod_handle to
                mov     __hInstance, eax  ; initialize _hInstance
                call    __startupd
                add     esp, 4      ; discard module_data parameter

                cmp     dword ptr [esp+8], 1    ; Check whether Process Attach
                jne     return

                mov     edx, fs:[4]
                mov     ecx, [save_stacktop  ]
                mov     [edx-8], ecx
                mov     ecx, [save_stacktop+4]
                mov     [edx-4], ecx

return:
                ret     12          ; return to NT
else
                push    0           ; NULL returns current module
                call    GetModuleHandleA
                mov     __hInstance, eax

                push    0           ; dummy return address
                jmp     __startup
endif

__acrtused      ENDP

ifdef   DLL
public          __GetExceptDLLinfo
else
publicdll       __GetExceptDLLinfo
endif

__GetExceptDLLinfo      proc    near
                jmp     __GetExceptDLLinfoInternal
__GetExceptDLLinfo      ENDP

_TEXT           ENDS

                END     __acrtused
