
.xlist
include kernel.inc
include tdb.inc
include pdb.inc
include kdos.inc
include eems.inc
include protect.inc
ifdef WOW
include vint.inc
endif
.list

externFP LoadLibrary
externFP LoadModule
externFP GlobalFree,
externFP GlobalFreeAll
externFP GlobalCompact
externFP FreeModule
externFP GlobalDOSFree
externFP FreeSelector
externFP GetProcAddress                  ; WIN32S
externFP ISetErrorMode                   ; WIN32S
externFP ISetHandleCount

externFP ExitKernelThunk
externNP DPMIProc

extrn   BUNNY_351:FAR

ifdef WOW
DRIVE_REMOTE    equ 4
externW  headTDB
externFP lstrlen
externFP WOWSetIdleHook
externFP GetDriveType
endif

externW pStackBot
;externW pStackMin
externW pStackTop

DataBegin

externB Kernel_flags
externB num_tasks
externB Kernel_InDOS
externB Kernel_InINT24

externB WOAName
externB grab_name
externB fBooting
externB graphics
externB fExitOnLastApp

externW cur_dos_PDB
externW Win_PDB
externW headPDB
externW topPDB
externW curTDB
externW curDTA
externW PHTcount
externW gmove_stack
externW MyCSSeg
externW wExitingTDB
externD lpSystemDir

if KDEBUG
externW allocTask
endif

if ROM
externD prevInt21Proc
endif

externD lpint21
externD pExitProc
if PMODE32
externD pDisplayCritSec
externW	PagingFlags
externD lpReboot
endif

ifdef   JAPAN
externD pJpnSysProc
endif

DataEnd

sBegin  DATA
externW gmove_stack


ifdef   PMODE32
ifndef WOW
WIN32S = 1           ; enable code for Win32S support
endif
endif

ifdef WIN32S
; Win32S support
selExecPE       DW      0
offExecPE       DW      0
endif

sEnd    DATA

assumes DS,NOTHING
sBegin	CODE
assumes CS,CODE

ife ROM
externD prevInt21Proc
endif

externNP Real_DOS
externNP PathDrvDSDX
externNP SetErrorDrvDSDX
externNP SetCarryRet
externNP ExitSchedule
externNP UnlinkObject
externNP final_call_for_DOS

externNP cmp_sel_address
externNP free_sel
externNP SegToSelector

if SDEBUG
externNP DebugExitCall
endif
externNP DeleteTask


;-----------------------------------------------------------------------;
; Set_DTA		(DOS Call 1Ah)					;
; 									;
; Simply records on a task basis the DTA.				;
; 									;
; Arguments:								;
; 									;
; Returns:								;
; 									;
; Error Returns:							;
; 									;
; Registers Preserved:							;
; 									;
; Registers Destroyed:							;
; 									;
; Calls:								;
; 									;
; History:								;
; 									;
;  Sat Jan 10, 1987 09:19:36p  -by-  David N. Weise   [davidw]          ;
; Wrote it.								;
;-----------------------------------------------------------------------;

	assumes ds, nothing
	assumes es, nothing

cProc	Set_DTA,<PUBLIC,NEAR>
cBegin nogen
	push	es
	SetKernelDS	es
	mov	curDTA.off,dx
	mov	curDTA.sel,ds
	mov	es,curTDB
	UnSetKernelDS	es
	cmp	es:[TDB_sig],TDB_SIGNATURE
	jne	Set_DTA_noTDB
	mov	es:[TDB_DTA].off,dx
	mov	es:[TDB_DTA].sel,ds
Set_DTA_noTDB:
	pop	es
	jmp	final_call_for_DOS
cEnd nogen


;-----------------------------------------------------------------------;
; SaveRegs								;
; 									;
; Does what it says.							;
;									;
; Arguments:								;
; 									;
; Returns:								;
; 									;
; Error Returns:							;
; 									;
; Registers Preserved:							;
; 									;
; Registers Destroyed:							;
; 									;
; Calls:								;
; 									;
; History:								;
; 									;
;  Fri Jan 16, 1987 09:57:49p  -by-  David N. Weise   [davidw]          ;
; Added this nifty comment block.					;
;-----------------------------------------------------------------------;

	assumes	ds, nothing
	assumes	es, nothing

cProc	SaveRegs,<PUBLIC,NEAR>
cBegin nogen

	xchg	dx, user_DX		; Return address in DX
	push	es
	push	bx
	push	ax
	push	cx
	push	si
	push	di
	and	USER_FL,11111110b	; clc flag
	push	dx
	mov	dx, user_DX		; Rescue DX for what it's worth
	cld

	ret
cEnd nogen

;-----------------------------------------------------------------------;
; RestoreRegs								;
; 									;
; Does what it says and (used to cli).					;
; 									;
; Arguments:								;
; 									;
; Returns:								;
; 									;
; Error Returns:							;
; 									;
; Registers Preserved:							;
; 									;
; Registers Destroyed:							;
; 									;
; Calls:								;
; 									;
; History:								;
; 									;
;  Fri Jan 16, 1987 10:00:41p  -by-  David N. Weise   [davidw]          ;
; Added this nifty comment block.					;
;-----------------------------------------------------------------------;

	assumes	ds, nothing
	assumes	es, nothing

cProc	RestoreRegs,<PUBLIC,NEAR>
cBegin nogen

	pop	di			; Return address
	xchg	di, user_BP		; Insert for ret later, get saved BP
	mov	bp, di
	dec	bp
	pop	di
	pop	si
	pop	cx
	pop	ax
	pop	bx
	pop	es
	pop	dx
	pop	ds
	ret				; SP points to user_BP
cEnd nogen

;-----------------------------------------------------------------------;
;                                                                       ;
;  Handle the Int21 func 67 call "Set Maximum Handle Count"             ;
;                                                                       ;
;-----------------------------------------------------------------------;

cProc   SetMaxHandleCount,<PUBLIC,NEAR>
cBegin  nogen
        pop     ds
        pop     bp                              ; clean up stack
        dec     bp

        cmp     bx, 255
        ja      smhc_err1

        push    bx
        push    cx
        push    dx

        cCall   ISetHandleCount,<bx>
        pop     dx
        pop     cx
        pop     bx

        cmp     ax, bx                          ; did we get everything?
        jne     smhc_err2
        clc
        jmp     smhcexit

smhc_err1:
        mov     ax,4                            ; too many open files
        stc                                     ; set carry flag
        jmp     smhcexit

smhc_err2:
        mov     ax,8                            ; not enough memory
        stc                                     ; set carry flag
smhcexit:
        STIRET
        ret


cEnd    nogen


;-----------------------------------------------------------------------;
; Set_Vector		(DOS Call 25h)					;
; Get_Vector		(DOS Call 35h)					;
;									;
;									;
; Arguments:								;
;									;
; Returns:								;
; 									;
; Error Returns:							;
; 									;
; Registers Preserved:							;
; 									;
; Registers Destroyed:							;
; 									;
; Calls:								;
; 									;
; History:								;
; 									;
;  Sat Jan 17, 1987 01:48:29a  -by-  David N. Weise   [davidw]          ;
; Added this nifty comment block.					;
;-----------------------------------------------------------------------;

	assumes	ds, nothing
	assumes	es, nothing

cProc	Set_Vector,<PUBLIC,NEAR>
cBegin nogen
	push	di
	push	es
	call	IsItIntercepted
	jnz	notintercepted
	SetKernelDS es
	mov	es, CurTDB		; We intercepted it, change
	UnSetKernelDS es		; vector in the TDB
	mov	es:[di].off, dx
	mov	es:[di].sel, ds
	jmps	sv_done 		; And just return
notintercepted:
	SetKernelDS es
	cmp	fBooting,1
	jz	sv_no_restrictions
	cmp	graphics,0		; in the stand alone OS/2 box?
	jz	@F
ifdef   JAPAN
        push    ax
        push    bx                      ; 04/23/91 -yukini
        mov     bx,0
        cCall   [pJpnSysProc], <bx,ax>  ; call System.JapanInquireSystem to
                                        ; get vector can be modified or not.
        test    ax,ax
        pop     bx
        pop     ax
        jz      sv_done                 ; jump if cannot be modified
else
	cmp	al,1Bh
	jz	sv_done
	cmp	al,1Ch
	jz	sv_done
endif
@@:	cmp	al,21h			; trying to reset our traps?
	jz	sv_done
	cmp	al,24h			; trying to reset our traps?
        jz      sv_done
        cmp     al,2fh                  ; setting idle detect vector?
        jnz     sv_no_restrictions      ; no, proceed normally
        push    ax
        push    dx
        push    ds
        cCall   WOWSetIdleHook          ; set the real hook back in Win32
        pop     ds
        pop     dx
        pop     ax
        jmp     bodacious_cowboys
sv_no_restrictions:
	cmp	al,21h
	jnz	bodacious_cowboys
	mov	lpint21.off,dx
	mov	lpint21.sel,ds
bodacious_cowboys:
	call	real_DOS

sv_done:
	pop	es
	pop	di
	pop	ds
	pop	bp			; clean up stack
	dec	bp
        STIRET

cEnd nogen

	assumes	ds, nothing
	assumes	es, nothing

cProc	Get_Vector,<PUBLIC,NEAR>
cBegin nogen
	pop	ds
	pop	bp			; clean up stack
	dec	bp
	push	di
	call	IsItIntercepted
	jnz	notintercepted1
	push	ds			; We intercepted it, get the
	SetKernelDS			; vector from the TDB
	mov	ds, CurTDB
	UnSetKernelDS
	mov	bx, [di]
	mov	es, [di+2]
	pop	ds
	pop	di
	jmps	gv_done
notintercepted1:
	pop	di
	call	real_DOS
gv_done:
        STIRET

cEnd nogen



cProc	IsItIntercepted,<PUBLIC,NEAR>
cBegin nogen
	mov	di, TDB_INTVECS
	cmp	al, 00h
	je	yes_intercepted
	add	di, 4
	cmp	al, 02h
	je	yes_intercepted
	add	di, 4
	cmp	al, 04h
	je	yes_intercepted
	add	di, 4
	cmp	al, 06h
	je	yes_intercepted
	add	di, 4
	cmp	al, 07h
	je	yes_intercepted
	add	di, 4
	cmp	al, 3Eh
	je	yes_intercepted
	add	di, 4
	cmp	al, 75h
yes_intercepted:
	ret
cEnd nogen


;-----------------------------------------------------------------------;
; ExecCall		(DOS Call 4Bh)					;
; 									;
; 									;
; Arguments:								;
; 									;
; Returns:								;
; 									;
; Error Returns:							;
; 									;
; Registers Preserved:							;
; 									;
; Registers Destroyed:							;
; 									;
; Calls:								;
; 									;
; History:								;
; 									;
;  Mon 07-Aug-1989 23:39:59  -by-  David N. Weise  [davidw]		;
; Added support for long command lines to WinOldApp.			;
;									;
;  Sat Jan 17, 1987 01:39:44a  -by-  David N. Weise   [davidw]		;
; Added this nifty comment block.					;
;-----------------------------------------------------------------------;

	assumes	ds, nothing
	assumes	es, nothing

cProc	ExecCall,<PUBLIC,NEAR>
cBegin nogen
	call	PathDrvDSDX		; Check drive
	jnc	EC1			; Drive OK
	call	SetErrorDrvDSDX 	; Set up errors
	jmp	SetCarryRet		; Error

EC1:	call	SaveRegs
	call	far ptr FarExecCall
	call	RestoreRegs
        STIRET
cEnd nogen


;-----------------------------------------------------------------------;
; TerminatePDB								;
;									;
; It calls DOS to terminate the current task.				;
;									;
; Arguments:								;
;	DI = exit code							;
; Returns:								;
;	nothing								;
; Error Returns:							;
;	nothing								;
; Registers Preserved:							;
;	none								;
; Registers Destroyed:							;
;									;
; Calls:								;
;									;
; History:								;
;									;
;-----------------------------------------------------------------------;

	assumes	ds, nothing
	assumes	es, nothing

cProc	TerminatePDB,<PUBLIC,NEAR>
cBegin	nogen

	SetKernelDS	ES
	mov	bx, ds				; DS is PDB being terminated
	cmp	cur_dos_PDB, bx			; Ensure DOS/anyone on the
	je	short @F			; int 21h chain has correct PDB
	mov	ah, 50h
	pushf
	call	prevInt21Proc
@@:
	mov	ax, ds:[PDB_Parent_PID]		; Parent PDB
	mov	Win_PDB, ax			; These will be changed by DOS
	mov	cur_dos_PDB, ax

	or	Kernel_Flags[2],KF2_WIN_EXIT
	mov	ax,di			; AL = exit code
	mov	ah, 0			; Alternative exit for PMODE which returns
	call	real_DOS		; let DOS clean up
	UnSetKernelDS	es

	errn$	DosExitReturn

cEnd	nogen

;
; The DOS terminate call above will return to
; the following label, DosExitReturn.  This is
; a separate procedure in order to be declared FAR.
;
	assumes	ds, nothing
	assumes	es, nothing

cProc	DosExitReturn,<PUBLIC,FAR>
cBegin nogen

	SetKernelDS ES
	mov	Kernel_InDOS,0
	mov	Kernel_InINT24,0
	and	Kernel_Flags[2],NOT KF2_WIN_EXIT
	retn

cEnd nogen

;-----------------------------------------------------------------------;
; ExitCall		(DOS Call 4Ch)					;
;									;
; It terminates the current task.					;
;									;
; Arguments:								;
;	AL = exit code							;
; Returns:								;
;	nothing								;
; Error Returns:							;
;	nothing								;
; Registers Preserved:							;
;	none								;
; Registers Destroyed:							;
;	none								;
; Calls:								;
;	TerminatePDB							;
;	GlobalFreeAll							;
;	UnlinkObject							;
;	DeleteTask							;
;	GlobalFree							;
;	FreeModule							;
; History:								;
;									;
;  Mon 07-Aug-1989 23:39:59  -by-  David N. Weise  [davidw]		;
; Removed WinOldApp support.						;
;									;
;  Sun Apr 26, 1987 03:20:05p  -by-  David N. Weise   [davidw]		;
; Made it switch stacks to the temp_stack because of EMS.		;
; 									;
;  Mon Sep 29, 1986 04:06:08p  -by-  Charles Whitmer  [chuckwh]		;
; Made it kill all threads in the current process.			;
;									;
;  Mon Sep 29, 1986 03:27:12p  -by-  Charles Whitmer  [chuckwh]		;
; Made it call UnlinkObject rather than do the work inline.		;
;									;
;  Mon Sep 29, 1986 09:22:08a  -by-  Charles Whitmer  [chuckwh]		;
; Documented it.							;
;-----------------------------------------------------------------------;

	assumes	ds, nothing
	assumes	es, nothing

cProc	ExitCall,<PUBLIC,NEAR>
cBegin          nogen

ifdef WOW
        ; Set to a Known DIR so that if an app was running over the network
        ; the user can disconnect once the app terminates.
        ; This also allows a subdirectory to be removed after a Win16 app
        ; had that dir as the current dir, but was terminated.

        SetKernelDS

        push    ax
        push    si
        push    dx
        push    ds

        lds     si,lpSystemDir          ; ds:si points to system directory
        mov     dl,[si]                 ; put drive letter into AL
        add     dl,-65                  ; subtract 'A' to get drive number
        mov     ah,0Eh
        call    real_DOS                ; select disk

        add     si,2                    ; let SI point to the first '\' past d:

        mov     al,[si + 1]             ; save first character after '\'
        push    ax

        mov     byte ptr [si + 1],0     ; null-terminate string after root dir
        mov     dx,si
        mov     ah,3Bh
        call    real_DOS                ; select directory

        pop     ax
        mov     [si + 1],al             ; restore string to its original state

        pop     ds
        pop     dx
        pop     si
        pop     ax
endif


if SDEBUG
        ;** Save the TDB of the currently exiting task.  We check for this
        ;**     in DebugWrite so that we don't get recursive
        ;**     debug strings at task exit time.  This is a gross hack
        ;**     for QCWin and their numerous param validation errors.
        mov     bx,curTDB               ;Get current task handle
        mov     wExitingTDB,bx          ;Save as exiting TDB
        cCall   DebugExitCall           ;Passes exit code in AL
endif ; SDEBUG

if PMODE32
        .386
        smov    fs, 0
        smov    gs, 0
        .286p

        xchg    di,ax                   ; DI = exit code

        cmp     graphics,1              ; is there a display driver around?
        jnz     @F
	mov	ax,1
ifndef WOW ; WOW doesn't have a display dirver to call
	cCall	pDisplayCritSec,<ax>	; tell display driver to shut up
endif
        or      Kernel_Flags[2],KF2_WIN386CRAZINESS
@@:     mov     ds,curTDB               ; DS = current TDB
        assumes ds,nothing
else
        xchg    di,ax                   ; DI = exit code
        mov     ds,curTDB               ; DS = current TDB
        UnSetKernelDS
endif

; We may have gotten here due to stack checking.  Let's make sure
;  that we are on a stack we can deal with.

        test    ds:[TDB_flags],TDBF_OS2APP
        jz      @F
        mov     ax,sp
        mov     ss:[pStackBot],ax
@@:     xor     ax,ax
        mov     ss:[pStackTop],ax

; remove the PDB from the chain

        mov     es,ds:[TDB_PDB]
        mov     dx,PDB_Chain
        mov     bx,dataOffset HeadPDB
        call    UnlinkObject

        xor     si,si                   ; source of zero

; Dec total # of tasks, if last task in system, then quit Windows completely.

        smov    es,ds
        assumes es,nothing
	SetKernelDS
ifdef WOW
	cmp	fExitOnLastApp,0	; Quit WOW when the last app dies ?
	jz	@f

	cmp	num_tasks,2		; Last Task (ingnoring WOWEXEC) ?
	jz	last_task
@@:
endif
        dec     num_tasks
	jnz	not_the_last_task

last_task:
IF PMODE32
        ;** Unhook local reboot VxD stuff
        cmp     WORD PTR lpReboot[2], 0 ;Reboot handler installed?
        je      @F                      ;No
        push    es
        mov     ax, 0201h               ;Reboot VxD #201:  Set callback addr
        xor     di, di                  ;Zero CS means no SYS VM local
        mov     es, di
        call    [lpReboot]              ;  reboot handler
        pop     es
@@:
ENDIF

        call    BUNNY_351

ifndef WOW				; For WOW ex just want to get out of here - no need to call USER16 or GDI16
	cCall	pExitProc,<si,si>	; this does not return
endif
        cCall   ExitKernelThunk,<si>

        assumes es, nothing
not_the_last_task:

; Signal( hTask, SG_EXIT, ExitCode, 0, Queue ) if we have a user signal proc

        push    es
        cmp     es:[si].TDB_USignalProc.sel,si
        jz      no_signal_proc
        mov     bx,SG_EXIT
        cCall   es:[si].TDB_USignalProc,<es,bx,di,es:[si].TDB_Module,es:[si].TDB_Queue>
no_signal_proc:

	pop	es

	mov	bl,6
	DPMICALL    0202h		 ; DPMI get exception handler vector
        push    cx
        push    dx

        mov     cx,cs
        lea     dx,exit_call_guts
        mov     bl,6
	DPMICALL    0203h		 ; DPMI set exception handler vector

        pop     dx
        pop     cx
;
; Generate an invalid opcode exception fault.  This causes DPMI to call
; our "exception handler."
;
	db	0fh,0ffh
exit_call_guts:
        FSTI                     ; we're called with ints disabled
        mov     bp,sp           ; BP -> RETIP RETCS EC IP CS FL SP SS
;
; Restore the previous invalid exception handler vector.
;
	mov	bl,6
	DPMICALL 0203h
;
; Point the return stack at Kernel's temporary stack.
;
        mov     ax,dataOffset gmove_stack
        mov     [bp+12],ax
        mov     ax,seg gmove_stack
        mov     [bp+14],ax
;
; Replace the return address on the DPMI fault handler routine with
; our exit code.
;
        lea     ax,ExitSchedule
        mov     [bp+6],ax
        mov     [bp+8],cs

        push    es

        cCall   GlobalFreeAll,<si>      ; free up all task data
        pop     es

; Remove from queue.

        push    es
        cCall   DeleteTask,<es>
        pop     es
        mov     ds,es:[TDB_PDB]         ; DS = current PDB

	UnsetKernelDS			; DS is PDB to terminate

	call	TerminatePDB		; Call DOS to close down files etc.

	ReSetKernelDS ES		; TerminatePDB returned with ES set

	xor	bp,bp			; set up valid frame
	mov	ds,curTDB

; If this task has a PHT, decrement the PHT count and clear the pointer
;  and zap the PHT pointer so we don't look at it anymore.
;  NOTE - BP contains a convenient zero.

	mov	ax,ds:[TDB_PHT].sel
	or	ax,ds:[TDB_PHT].off
	jz	no_PHT
	mov	ds:[TDB_PHT].sel,bp
	mov	ds:[TDB_PHT].off,bp
	dec	PHTcount		; dec # tasks with PHT's
no_PHT:
	UnSetKernelDS	es
	cCall	FreeModule,<ds:[TDB_Module]>	; Free the module for this task
	xor	ax,ax
	mov	ds:[TDB_sig],ax 	; Mark TDB as invalid

        ;** Nuke any JFN that is outside the PDB.  We can tell that the
        ;**     JFN points outside the PDB if the offset is zero.  PDB
        ;**     JFN's never have a zero offset and outside ones always do.
	push	ds
	mov	ds, ds:[TDB_PDB]
        cmp     WORD PTR ds:[PDB_JFN_Pointer][0], 0 ;JFN pointer into PDB?
        jne     EC_NoFreeJFN            ;Yes, don't free anything
        push    WORD PTR ds:[PDB_JFN_Table] ;Get our selector
        call    GlobalDOSFree
EC_NoFreeJFN:

	SetKernelDS
 
        cmp     num_tasks,1             ; Last task? (except wowexec)
        jne     @f
        
        cCall   GlobalCompact,<-1, -1>      ; free up as many pages as possible
@@:
	mov	bx, topPDB
	mov	Win_PDB, bx
	mov	cur_dos_PDB, bx
	mov	ah, 50h
	pushf
	call	prevInt21Proc		; Set PDB to KERNEL's
	pop	ds
	UnSetKernelDS
	xchg	bx, ds:[TDB_PDB]
	cCall	free_sel,<bx>		; Free the PDB selector

	call	far ptr FreeTDB		; Tosses PDB's memory
        SetKernelDS
ifndef WOW
        mov     curTDB,0        ; We can use this, setting curTDB = 0
else
        ;; We do this a little later - see tasking.asm exitschedule
endif
    if PMODE32			;  in rmode as well in the next rev
	or	PagingFlags, 8	;  to save a few bytes.
    endif	

        ;** Task has been nuked.  Clear the DebugWrite task exiting flag
        mov     wExitingTDB,0

        retf                    ; To ExitSchedule
cEnd nogen	

	assumes	ds, nothing
	assumes	es, nothing

cProc	FreeTDB, <PUBLIC,FAR>
cBegin nogen

	cCall	FreeSelector,<ds:[TDB_MPI_Sel]>
	mov	ax,ds
if KDEBUG
;
; If we're freeing the alloc break task, zero out the global.
;
        SetKernelDS
        cmp     ax,allocTask
        jnz     @F
        mov     allocTask,0
@@:
        UnSetKernelDS
endif
	smov	ds,0
	cCall	GlobalDOSFree,<ax>
	ret

cEnd nogen

;-----------------------------------------------------------------------;
; set_PDB			(DOS Call 50h)				;
; 									;
; This is an undocumented DOS call to set the current PDB.		;
; DOS does not check for ^C's on this call, in fact it never turns	;
; on the interrupts.							;
;									;
; Arguments:								;
; 									;
; Returns:								;
; 									;
; Error Returns:							;
; 									;
; Registers Preserved:							;
; 									;
; Registers Destroyed:							;
; 									;
; Calls:								;
; 									;
; History:								;
; 									;
;  Fri Jan 23, 1987 07:07:14p  -by-  David N. Weise   [davidw]          ;
; Wrote it.								;
;-----------------------------------------------------------------------;

	assumes	ds, nothing
	assumes	es, nothing

cProc	set_PDB,<PUBLIC,NEAR>
cBegin nogen
	SetKernelDS
	mov	cur_dos_PDB,bx
	mov	Win_PDB,bx
	mov	ds,curTDB
	assumes ds,nothing
	mov	ds:[TDB_PDB],bx
	call	real_DOS
	pop	ds
	pop	bp			; clean up stack
	dec	bp
        STIRET
cEnd nogen


;-----------------------------------------------------------------------;
; get_PDB								;
;									;
; This is an undocumented DOS call to set the current PDB.		;
; DOS does not check for ^C's on this call, in fact it never turns	;
; on the interrupts.							;
; Trapping this is superfluous is real mode but necessary in protect	;
; mode since the DOS extender may not be doing the segment		;
; translation properly. 						;
;									;
; Entry:								;
;									;
; Returns:								;
;									;
; Registers Destroyed:							;
;									;
; History:								;
;  Tue 13-Jun-1989 18:22:16  -by-  David N. Weise  [davidw]		;
; Wrote it.								;
;-----------------------------------------------------------------------;

	assumes ds,nothing
	assumes es,nothing

cProc	get_PDB,<PUBLIC,NEAR>
cBegin nogen
	SetKernelDS
	call	real_DOS
	mov	bx,cur_dos_PDB
	pop	ds
	pop	bp			; clean up stack
	dec	bp
        STIRET
cEnd nogen

sEnd code

sBegin NRESCODE
assumes cs, NRESCODE
assumes	ds, nothing
assumes	es, nothing

externNP MapDStoDATA


;-----------------------------------------------------------------------;
; BuildPDB								;
; 									;
; 									;
; Arguments:								;
; 									;
; Returns:								;
; 									;
; Error Returns:							;
; 									;
; Registers Preserved:							;
; 									;
; Registers Destroyed:							;
; 									;
; Calls:								;
; 									;
; History:								;
; 									;
;  Thu 04-Jan-1990 20:15:27  -by-  David N. Weise  [davidw]		;
; Made it avoid closing cached files if the PDB being copied is not	;
; the topPDB.  This is for supporting inheriting a parents files.	;
;									;
;  Mon 11-Sep-1989 19:13:52  -by-  David N. Weise  [davidw]		;
; Removed returning validity in AX, and removed copying of FCBs.	;
;									;
;  Mon 07-Aug-1989 23:39:59  -by-  David N. Weise  [davidw]		;
; Added support for long command lines to WinOldApp.			;
;									;
;  Sun Jan 18, 1987 00:27:52a  -by-  David N. Weise   [davidw]		;
; Added this nifty comment block.					;
;-----------------------------------------------------------------------;

	assumes	ds, nothing
	assumes	es, nothing

cProc	BuildPDB,<PUBLIC,FAR>,<si,di>
	ParmW	oldPDB
	ParmW	newPDB
	ParmD	ParmBlock
	ParmW	newSize
        ParmW   fWOA
cBegin
	call	MapDStoDATA
	ReSetKernelDS

	push	Win_PDB			; Save current PDB

	mov	bx,oldPDB		; set current PDB for copy
	mov	Win_PDB, bx

	mov	dx,newPDB
	mov	si,newSize
	mov	ah,55h			; duplicate PDB
	int	21h

	mov	bx, oldPDB
	mov	dx, newPDB
	mov	cur_dos_PDB, dx		; DOS call 55h sets the PDB to this

nothing_to_close:

	pop	Win_PDB			; restore former PDB

	xor	di,di

	mov	cx, MyCSSeg
	mov	ds,dx
	UnSetKernelDS
	mov	es,dx
	add	si,dx
	mov	ax,oldPDB
	mov	[di].PDB_Parent_PID,ax	; parent = OldPDB
	mov	[di].PDB_Block_Len,si

	mov	[di].PDB_Exit.off,codeOffset DosExitReturn
	mov	[di].PDB_Exit.sel, cx

; No private global heap yet.

	mov	[di].PDB_GlobalHeap.lo,di
	mov	[di].PDB_GlobalHeap.hi,di

; Set up proper command line stuff.

	lds	si,ParmBlock
	lds	si,ds:[si].lpcmdline	; command line
	mov	di,PDB_DEF_DTA
        mov     cx,di
        cmp     fWOA,0
	jz	@F			; Winoldap can have long command line
        mov     cx,ds:[si]              ; get byte count
        cld
        movsb                           ; copy count byte
        inc     cx
        inc     si
@@:     rep     movsb                   ; Store command line.

cEnd


cProc	FarExecCall,<PUBLIC,FAR>
cBegin nogen

; Check if file extension is .COM, .BAT, .PIF, if so it needs emulation...

        cld
        les     di,User_DSDX


ifdef WOW
;
;  Wow LoadModule handles all forms of exec including
;  pe images, com, bat, pif files etc.
;
        lds     si,User_ESBX
	regptr	esdx,es,dx
	regptr	dssi,ds,si
        cCall   LoadModule,<esdx,dssi>
        cmp     ax, LME_MAXERR          ; check for error...
        jae     ex8
        jmp short ex7                     ; no, return error

else

        mov     cx,-1
	xor	al,al
	repnz	scasb			; scan to end of string
	neg	cx
	dec	cx			; cx has length (including null)
	mov	ax,es:[di-5]
	or	ah,20h
	mov	bx,es:[di-3]		; complete check for .COM
	or	bx,2020h		; convert to lower case

	cmp	ax,'c.' 		; check for .COM file extension
	jnz	ex1b			; no match...attempt load module
	cmp	bx,'mo'
	jz	ex4			; yes! go immediatly to GO

ex1b:	cmp	ax,'b.' 		; check for .BAT extension...
	jnz	ex1c
	cmp	bx,'ta'
	jz	ex4

ex1c:	cmp	ax,'p.' 		; check for .PIF extension...
	jnz	ex2
	cmp	bx,'fi'
        jz      ex4

ex2:    lds     si,User_ESBX
	regptr	esdx,es,dx
	regptr	dssi,ds,si
        push    cx                      ; save length of string
	cCall	LoadModule,<esdx,dssi>
        pop     cx
        cmp     ax, LME_MAXERR          ; check for error...
	jb	ex3
	jmp	ex8
ex3:    cmp     ax, LME_INVEXE		; wrong format?
	jz	ex4
	cmp     ax, LME_EXETYPE		; quick basic app
        jz      ex4

        cmp     ax, LME_PE              ; Win32 PE format
        jz      @F
	jmp	ex7			; no, return error
@@:


ifdef WIN32S
	push    cx
; Win32S support -  (AviN)   11-19-91

        lds     si,User_DSDX
	push	ds
        push    si
        lds     si,User_ESBX
        push    ds:[si+4]           ; CmdLine sel
        push    ds:[si+2]           ;         offset

        les     bx, ds:[si+6]       ; FCB1
        push    es:[bx+2]           ; nCmdShow

        call    FAR PTR ExecPE
        pop     cx

        cmp     ax, 32
        jbe     @F
        jmp     ex8
@@:
        cmp     ax, 11                  ; NOT PE
        je      @F
        jmp     ex7

@@:

; end of Win32S support
endif

ex4:

; Run an old application
;
; If we are running in the OS/2 3x box, we do not support running old
; apps.  If someone trys this, put up a nasty message and return with
; an error.  (Thu 12-Nov-1987 : bobgu)


	mov	dx,cx			; save length of file name
	sub	sp,256			; make room for command line
	smov	es,ss
	mov	di,sp
	lds	si,User_ESBX
	lds	si,ds:[si].lpcmdline
	xor	ax,ax
	xor	cx,cx
	mov	cl,ds:[si]
	inc	cx
        movsb
        stosb
        rep     movsb
	mov	cx,dx
	lds	si,User_DSDX
	rep	movsb
	mov	byte ptr es:[di][-1],10	; terminate with line feed
	mov	di,sp
	add	es:[di],dx

	mov	bx,es
	push	ds
	call	MapDStoDATA
	smov	es, ds
	pop	ds
        ReSetKernelDS es

        test    Kernel_flags[2],KF2_DOSX ; DOSX winoldap doesn't need special
	jnz	@F			 ;  special handling
	mov	ax,dataOffset grab_name
	push	bx
	push	dx
	push	es
	cCall	LoadLibrary,<es,ax>
	pop	es
	pop	dx
	pop	bx
	cmp	ax,32
	jae	@F
	add	sp, 256			; undo damage to stack
	jmps	ex7
@@:

        or      Kernel_flags[1],KF1_WINOLDAP
        lds     si,User_ESBX
	mov	ds:[si].lpcmdline.off,di
	mov	ds:[si].lpcmdline.sel,bx
	mov	dx,dataOffset WOAName
	regptr	esdx,es,dx
	regptr	dssi,ds,si
	cCall	LoadModule,<esdx,dssi>
	assumes	es, nothing
	add	sp,256
	cmp	ax,32			; check for error...
	jae	ex8
	cmp	ax,2			; file not found?
	jnz	ex7			; no, return error
        mov     al,23                   ; flag WINOLDAP error

;; ndef wow
endif

ex7:    or      User_FL,1               ; set carry flag
	or	ax,ax			; out of memory?
	jnz	ex8
	mov	ax,8h			; yes, return proper error code
ex8:	mov	User_AX,ax		; return AX value

	ret
cEnd nogen


ifdef WIN32S
SZW32SYS        db  "W32SYS.DLL", 0
ExecPEOrd       equ  3

;-----------------------------------------------------------------------;
; ExecPE
; Get ExecPE address in W32SYS.DLL, and call it
; 11-13-91   AviN   created
;-----------------------------------------------------------------------;

cProc   ExecPE,<PUBLIC,FAR>
cBegin	nogen
	push	ds
        mov     ax, SEG selExecPE
        mov     ds, ax

assumes DS, DATA

        mov     dx, selExecPE          ; check for a valid address
        or      dx, dx
        jnz     ep_x

        mov     ax, offExecPE
        or      ax, ax
        jnz     ep_err                 ; already failed, don't try again


        cCall   ISetErrorMode, <8000h>
        push    ax

        lea     ax, SZW32SYS
        cCall   LoadLibrary,<cs, ax>

        pop     dx
        push    ax
        cCall   ISetErrorMode,<dx>      ; restore original error mode
        pop     ax

        cmp     ax, 32
        jbe     ep_err

        push    ax
        push    0
        push    ExecPEOrd
        cCall   GetProcAddress
        or      dx,dx
        jz      ep_err
        mov     selExecPE, dx
        mov     offExecPE, ax
ep_x:

        pop     ax                      ; saved DS
        push    selExecPE               ; jmp to ExecPE
        push    offExecPE
        mov     ds, ax
        retf

ep_err:
                                        ; if w32sys support no available return
        mov     ax, 11                  ; invalid module format
        mov     offExecPE, ax           ; and record for next time

        pop     ds
	retf    10                      ; pop ExecPE parameters


assumes DS,NOTHING
cEnd    nogen
endif


sEnd NRESCODE

sBegin MISCCODE
assumes cs, misccode
assumes ds, nothing
assumes es, nothing

externNP MISCMapDStoDATA

;-----------------------------------------------------------------------;
;                                                                       ;
;  Get the Current PDB without doing a DOS call.                        ;
;                                                                       ;
;-----------------------------------------------------------------------;

cProc   GetCurrentPDB,<PUBLIC,FAR>
cBegin  nogen
        push    ds
        call    MISCMapDStoDATA
        ReSetKernelDS
        mov     dx,TopPDB
        mov     ds,curTDB
        UnSetKernelDS
        mov     ax,ds:[TDB_PDB]
        pop     ds
        ret
cEnd    nogen


sEnd MISCCODE

end

