;[]------------------------------------------------------------[] ;| C0W.ASM -- Start Up Code For Windows | ;[]------------------------------------------------------------[] ; ; C/C++ Run Time Library - Version 6.5 ; ; Copyright (c) 1991, 1994 by Borland International ; All Rights Reserved. ; locals __C0__ = 1 include RULES.ASI ASSUME CS:_TEXT, DS:DGROUP public __acrtused ;satisfy MS for now __acrtused equ 0 IFNDEF __DPMI16__ public __WINMAINCALL ; used internally ENDIF public __INITAPPCALLED ; used internally IFNDEF __DPMI16__ extrn WINMAIN:DIST ENDIF extrn INITAPP:far extrn INITTASK:far extrn FATALEXIT:far extrn WAITEVENT:far extrn LOCKSEGMENT:far extrn UNLOCKSEGMENT:far extrn GETWINFLAGS:far IFDEF __DPMI16__ extrn _main:DIST extrn _OkToInitWindowsRTL:DIST extrn __abort:DIST ENDIF extrn _exit:DIST extrn __exit:DIST extrn __exitbuf:DIST extrn __exitfopen:DIST extrn __exitopen:DIST extrn __setupio:near ;required! extrn __ExceptInit:DIST public __DestructorCount ;Offset to global destructor count __DestructorCount EQU 10H public __Exception_list ;Offset to global exception list __Exception_list EQU 14H NULL segment db 16 dup (0) ;Windows db 4 dup (0) ;destructor count db 2 dup (0) ;exception list db 4 dup (0) ;exception vptr db 6 dup (0) ;reserved db 2 dup (0) ;VBX control jump vector ;MUST be at SS:20h db 2 dup (0) ;reserved ends _CVTSEG segment public __RealCvtVector __RealCvtVector label word ends _SCNSEG segment public __ScanTodVector __ScanTodVector label word ends _FPSEG segment public __FPVector __FPVector dd 0 ends _DATA segment public _errno _errno dw 0 public __protected __protected dw 0 public __8086 __8086 dw 0 public __8087 __8087 dw 0 public __psp __psp dw 0 public __hInstance __hInstance dw 0 public __hPrev __hPrev dw 0 public __pszCmdline __pszCmdline dw 0 public __cmdShow __cmdShow dw 0 public __version __version label word public __osversion __osversion label word public __osmajor __osmajor db 0 public __osminor __osminor db 0 public __osmode ;Used for OS/2 protected mode by MS, __osmode db 0 ; currently set to 0 under Windows public __WinAllocFlag ;Used by malloc to get additional flags __WinAllocFlag dw 0 ; to pass to GlobalAlloc (for DLL use) public __LockWIN87EM ;Used do lock down WIN87EM to avoid __LockWIN87EM dw 1 ; DLL unload ordering problem public __abend __abend dw 0 ;Signals abnormal end, don't run destructors etc. IFDEF __DPMI16__ extrn __C0environ:dword extrn __C0argv:dword extrn __C0argc:word ENDIF CopyRight db 'Borland C++ - Copyright 1994 Borland Intl.',0 IFDEF __DPMI16__ DPMI16Error_s db 'This DPMI16 application was linked incorrectly and' db ' will fail.',10,13,'$' ENDIF ends _TEXT segment Main proc near ;Windows initialization. Sets up registers and stack. IFDEF __DPMI16__ mov ax, seg DGROUP mov ds, ax ENDIF push bx cx es xor ax,ax push ax call __ExceptInit pop ax pop es cx bx ;INITTASK returns: ; 'Failure: ; AX = zero if it failed ; Success: ; AX = 1 ; CX = stack limit ; DX = cmdShow parameter to CreateWindow ; ES:BX = -> DOS format command line (ES = PSP address) ; SI = hPrevinstance ; DI = hinstance call INITTASK or ax,ax jnz @@OK jmp @@Fail @@OK: mov word ptr ss:[__Exception_list], -1 mov __psp,es mov word ptr __pszCmdline,bx mov __hPrev,si mov __hInstance,di mov __cmdShow,dx IF LDATA EQ false mov ax,-1 push ax call LOCKSEGMENT ENDIF ;Clear _BSS, uninitialized data area IFNDEF __HUGE__ xor ax, ax push ds pop es mov di,offset DGROUP:BeginBSS mov cx,offset DGROUP:EndBSS sub cx,di cld rep stosb ENDIF ;Init the Windows App xor ax,ax push ax call WAITEVENT push __hInstance call INITAPP __INITAPPCALLED:or ax,ax jnz @@InitOK jmp @@Fail @@InitOK: ;Determine DOS version mov ah, 30h int 21h mov __version, ax ; save minor and major revision ;Determine whether we are in protected mode call GETWINFLAGS test ax,1 ; WF_PMODE = 1 jz @@realmode ; Note: GETWINFLAGS returns a long, ; so if WF_PMODE changed it could be ; in the high word. mov __protected, 8 ; Eight is for convenience. @@realmode: ;Test for 8086/8087 presence test ax,0400h ; WF_8087 = 0x0400 jz @@no8087 mov __8087, 1 @@no8087: and ax,08h+04h+02h ; WF_CPU486|WF_CPU386|WF_CPU286 shr ax,1 ; Convert to 4 or 2 or 1 or 0 test ax,0004h ; Have 4, 486 done jnz @@NoAdjust or ax,ax ; Have 0, 8086 done jz @@NoAdjust inc ax ; Have 2 or 1, need 3 or 2 @@NoAdjust: mov __8086,ax ; Set CPU Type IFDEF __DPMI16__ ; ; Here we attempt to prevent an early death caused by linking ; the libs in the wrong order ; call _OkToInitWindowsRTL or ax, ax jnz DPMI16Error ENDIF ;Call our initialization functions, including C++ static constructors. mov ax,ds mov es,ax mov si,offset DGROUP:InitStart ;si = start of table mov di,offset DGROUP:InitEnd ;di = end of table call Initialize IFDEF __DPMI16__ ;Set up and call _main for DPMI16 application push word ptr [__C0environ+2] push word ptr [__C0environ] push word ptr [__C0argv+2] push word ptr [__C0argv] push [__C0argc] call _main ELSE ;Set up and call WinMain for Windows application push __hInstance push __hPrev push __psp push word ptr __pszCmdline push __cmdShow __WINMAINCALL: call WINMAIN ENDIF push ax ; Push return value cmp __abend, 0 jne @@abnormalexit call _exit ; Normal exit @@abnormalexit: call __exit ; Abnormal exit, don't call destructors etc. IFDEF __DPMI16__ DPMI16Error: mov ah, 9 mov dx, offset DPMI16Error_s int 21h call __abort ENDIF ;--------------------------------------------------------------------------- ; _cleanup() call all #pragma exit cleanup routines. ; _checknull() check for null pointer zapping copyright message ; _terminate(int) exit program with error code ; _restorezero() restore interrupt vectors ; ; These functions are called by exit(), _exit(), _cexit(), ; and _c_exit(). ;--------------------------------------------------------------------------- ; Call cleanup routines __cleanup PROC DIST PUBLIC __cleanup mov ax,ds mov es,ax push si push di mov si,offset DGROUP:ExitStart mov di,offset DGROUP:ExitEnd call Cleanup pop di pop si ret __cleanup ENDP ; Check for null pointers before exit. NO-OP on Windows. __checknull PROC DIST PUBLIC __checknull ret __checknull ENDP ; Restore grabbed interrupt vectors. NO-OP on Windows. __restorezero PROC DIST PUBLIC __restorezero ret __restorezero ENDP ; Exit to DOS __terminate PROC DIST PUBLIC __terminate IF LDATA EQ false mov ax,-1 push ax call UNLOCKSEGMENT ENDIF mov bp,sp mov al,[bp+cPtrSize] mov ah,4ch ;exit int 21h __terminate ENDP @@Fail: mov al,0ffh push ax call _exit mov ah,4ch ;exit int 21h endp ; Return default data segment in AX __GetDGROUP PROC FAR PUBLIC __GetDGROUP mov ax, ss ret endp ;------------------------------------------------------------------ ; Loop through a startup/exit (SE) table, ; calling functions in order of priority. ; ES:SI is assumed to point to the beginning of the SE table ; ES:DI is assumed to point to the end of the SE table ; First 64 priorities are reserved by Borland ;------------------------------------------------------------------ PNEAR EQU 0 PFAR EQU 1 NOTUSED EQU 0ffh SE STRUC calltype db ? ; 0=near,1=far,ff=not used priority db ? ; 0=highest,ff=lowest addrlow dw ? addrhigh dw ? SE ENDS Initialize proc near @@Start: mov ax,100h ;start with lowest priority mov dx,di ;set sentinel to end of table mov bx,si ;bx = start of table @@TopOfTable: cmp bx,di ;and the end of the table? je @@EndOfTable ;yes, exit the loop cmp es:[bx.calltype],NOTUSED;check the call type je @@Next mov cl, es:[bx.priority] ;move priority to CX xor ch, ch cmp cx,ax ;check the priority jae @@Next ;too high? skip mov ax,cx ;keep priority mov dx,bx ;keep index in dx @@Next: add bx,SIZE SE ;bx = next item in table jmp @@TopOfTable @@EndOfTable: cmp dx,di ;did we exhaust the table? je @@Done ;yes, quit mov bx,dx ;bx = highest priority item cmp es:[bx.calltype],PNEAR ;is it near or far? mov es:[bx.calltype],NOTUSED;wipe the call type push es ;save es je @@NearCall @@FarCall: call DWORD PTR es:[bx.addrlow] pop es ;restore es jmp short @@Start @@NearCall: call WORD PTR es:[bx.addrlow] pop es ;restore es jmp short @@Start @@Done: ret endp Cleanup proc near @@Start: mov ah,0 ;start with highest priority mov dx,di ;set sentinel to end of table mov bx,si ;bx = start of table @@TopOfTable: cmp bx,di ;and the end of the table? je @@EndOfTable ;yes, exit the loop cmp es:[bx.calltype],NOTUSED;check the call type je @@Next cmp es:[bx.priority],ah ;check the priority jb @@Next ;too low? skip mov ah,es:[bx.priority] ;keep priority mov dx,bx ;keep index in dx @@Next: add bx,SIZE SE ;bx = next item in table jmp @@TopOfTable @@EndOfTable: cmp dx,di ;did we exhaust the table? je @@Done ;yes, quit mov bx,dx ;bx = highest priority item cmp es:[bx.calltype],PNEAR ;is it near or far? mov es:[bx.calltype],NOTUSED;wipe the call type push es ;save es je @@NearCall @@FarCall: call DWORD PTR es:[bx.addrlow] pop es ;restore es jmp short @@Start @@NearCall: call WORD PTR es:[bx.addrlow] pop es ;restore es jmp short @@Start @@Done: ret endp ends end Main