You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
385 lines
10 KiB
385 lines
10 KiB
TITLE LDAPPL - AppLoader Interface
|
|
|
|
IFNDEF NO_APPLOADER ;* entire file for AppLoader
|
|
|
|
.xlist
|
|
include kernel.inc
|
|
include newexe.inc
|
|
include tdb.inc
|
|
include appl.inc
|
|
include protect.inc
|
|
.list
|
|
|
|
DataBegin
|
|
|
|
externW pGlobalHeap
|
|
|
|
DataEnd
|
|
|
|
sBegin CODE
|
|
externNP SetOwner
|
|
externFP set_discarded_sel_owner
|
|
sEnd CODE
|
|
|
|
externFP MyOpenFile
|
|
externFP FarLoadSegment
|
|
externFP FarMyAlloc
|
|
externNP Int21Handler
|
|
IF KDEBUG ;See comment below where this function is used
|
|
externFP AppLoaderEntProcAddress
|
|
ELSE
|
|
externFP FarEntProcAddress
|
|
ENDIF
|
|
externFP GlobalHandle
|
|
externFP Far_get_temp_sel
|
|
externFP Far_free_temp_sel
|
|
|
|
sBegin NRESCODE
|
|
assumes CS,NRESCODE
|
|
assumes DS,NOTHING
|
|
assumes ES,NOTHING
|
|
|
|
externNP MapDSToDATA
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; BootAppl ;
|
|
; ;
|
|
; Boots (i.e. starts) an AppLoader application ;
|
|
; Loads (and relocates) first segment (must be CODE/FIXED/PRELOAD) ;
|
|
; Validates the APPL magic word ;
|
|
; Calls APPL boot procedure ;
|
|
; ;
|
|
; Arguments: ;
|
|
; parmW hexe (handle to exe header) ;
|
|
; parmW fh (file handle) ;
|
|
; ;
|
|
; Returns: ;
|
|
; AX != 0 => ok ;
|
|
; ;
|
|
; Error Returns: ;
|
|
; AX == 0 => error ;
|
|
; ;
|
|
; Registers Preserved: ;
|
|
; ;
|
|
; Registers Destroyed: ;
|
|
; ;
|
|
; Calls: ;
|
|
; various ;
|
|
; ;
|
|
; History: ;
|
|
; ;
|
|
; Thu Oct 01, 1987 11:10:06a -by- David N. Weise [davidw] ;
|
|
; Changed the return values to NOT return ZF. ;
|
|
; ;
|
|
; Thu Jul 30, 1987 11:56:34a -by- Scott A. Randell [scottra] ;
|
|
; Created it. ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
cProc BootAppl,<NEAR,PUBLIC>,<si>
|
|
parmW hexe
|
|
parmW fh
|
|
cBegin BootAppl
|
|
|
|
mov es,hexe
|
|
mov si,es:[ne_segtab] ;* es:si => segtab
|
|
mov ax,es:[si].ns_flags ;* first segment
|
|
test ax,NSMOVE
|
|
jnz @f ;* PMode loader will set the
|
|
jmp bal_error ;* moveable flag for us
|
|
@@:
|
|
|
|
test ax,NSPRELOAD
|
|
jz bal_error ;* must be preload
|
|
|
|
;* * load in first segment (turn off Alloced/Loaded, and DS requirement)
|
|
and ax,not NSALLOCED+NSLOADED+NSUSESDATA
|
|
mov es:[si].ns_flags,ax ;* update flags
|
|
mov ax,1 ;* first segment
|
|
cCall FarLoadSegment,<es,ax,fh,fh>
|
|
jcxz bal_fail ;* not enough memory
|
|
|
|
;* * now validate APPL header
|
|
mov es,ax
|
|
push es
|
|
cCall Far_get_temp_sel
|
|
xor bx,bx ;* es:bx => first segment
|
|
cmp es:[bx].magicAppl,magicApplCur ;* current version ?
|
|
;* (no backward compatibility)
|
|
jne bal_error_popes
|
|
|
|
;* * fill in global information
|
|
mov word ptr es:[bx].lppsMob,dataOffset pGlobalHeap
|
|
mov ax,codeBase ;* segment address of FIXED KERNEL
|
|
|
|
push ds
|
|
call MapDStoData
|
|
mov word ptr es:[bx].lppsMob+2,ds ;* segment address of krnl data
|
|
pop ds
|
|
|
|
mov word ptr es:[bx].pfnKernelAlloc,codeOffset FarMyAlloc
|
|
mov word ptr es:[bx].pfnKernelAlloc+2,ax
|
|
|
|
; In DEBUG, we really want RIPs to be able to happen when we don't
|
|
; find ordinals. This saves an enormous amount of debugging
|
|
; time!! The entry point AppLoaderEntProcAddress only exists
|
|
; in debug and allows RIPs to happen (unlike FarEntProcAddress
|
|
; which is the same entry point used for GetProcAddress which
|
|
; should not RIP).
|
|
IF KDEBUG
|
|
mov word ptr es:[bx].pfnEntProcAddress,codeOffset AppLoaderEntProcAddress
|
|
ELSE
|
|
mov word ptr es:[bx].pfnEntProcAddress,codeOffset FarEntProcAddress
|
|
ENDIF
|
|
mov word ptr es:[bx].pfnEntProcAddress+2,ax
|
|
;* * extra entry for Protect Mode only
|
|
mov word ptr es:[bx].pfnSetOwner,codeOffset MySetOwner
|
|
mov word ptr es:[bx].pfnSetOwner+2,ax
|
|
|
|
mov ax,es
|
|
pop es
|
|
cCall Far_free_temp_sel,<ax>
|
|
;* * call the start procedure
|
|
cCall es:[pfnBootAppl], <hexe, fh> ;* returns BOOL
|
|
|
|
bal_end: ;* ax
|
|
cEnd BootAppl
|
|
|
|
|
|
bal_error_popes: ;* an error occured (pop es if in PMODE)
|
|
mov ax,es
|
|
pop es
|
|
cCall Far_free_temp_sel,<ax>
|
|
bal_error: ;* an error occured
|
|
if KDEBUG
|
|
int 3
|
|
endif
|
|
bal_fail: ;* Boot failed (not enough memory)
|
|
xor ax,ax
|
|
jmps bal_end
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; ExitAppl ;
|
|
; ;
|
|
; Exit last instance of an APPLOADER application ;
|
|
; ;
|
|
; Arguments: ;
|
|
; parmW hexe (handle to exe header) ;
|
|
; ;
|
|
; Returns: ;
|
|
; N/A ;
|
|
; ;
|
|
; History: ;
|
|
; ;
|
|
; Sat Sep 19, 1987 15:55:19 -by- Scott A. Randell [scottra] ;
|
|
; Created it ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
cProc ExitAppl,<NEAR,PUBLIC>
|
|
parmW hexe
|
|
cBegin ExitAppl
|
|
|
|
; The apps with loaders don't do anything in their exit code except try
|
|
; to close a bogus file handle, so we just will not make this call
|
|
; anymore. This call runs on the kernel PSP, so if the app picked a valid
|
|
; kernel file handle, that file got closed. 0 seems to be a popular
|
|
; handle to inadvertently close. Newer apps do/will not have their own
|
|
; loaders.
|
|
|
|
ifdef DEAD_CODE ;--------------------------------------------------------
|
|
|
|
mov es,hexe
|
|
mov bx,es:[ne_segtab] ;* es:si => segtab
|
|
|
|
;* * first segment is the AppLoader
|
|
mov ax,es:[bx].ns_handle ;* handle
|
|
or ax, ax ; Out of memory, couldn't load segment?
|
|
jz exa_error
|
|
HtoS ax ;* back to ring 1
|
|
|
|
push bx
|
|
lar bx, ax
|
|
test bh, DSC_PRESENT ; Fix a WinWord bug
|
|
pop bx
|
|
jz exa_error
|
|
|
|
mov es,ax
|
|
;* * test to make sure that an APPL is there
|
|
cmp es:[magicAppl],magicApplCur
|
|
jne exa_error
|
|
|
|
; The following hack sets up SS to have a 64k limit before calling the
|
|
; app's exit procedure. Added 12/18/90 to work around a bug in the
|
|
; Excel & WinWord app loader that references a bogus offset from SS. In
|
|
; the past the stack segment at this point already had a large limit, but
|
|
; when the data segment was moved out of the kernel's code segment and
|
|
; the limit decreased to the actual DS size, the Excel/WinWord offset
|
|
; is now beyond the segment limit.
|
|
|
|
push ss ;save current SS
|
|
push es ;seg 1 handle
|
|
smov es,ss ;get temp selector takes
|
|
cCall far_get_temp_sel ; and returns selector in ES
|
|
smov ss,es ;SS now has max limit
|
|
pop es ;seg 1 handle
|
|
cCall es:[pfnExitAppl], <hexe>
|
|
|
|
mov ax,ss ;return to original SS and
|
|
pop ss ; free temp selector
|
|
cCall far_free_temp_sel,<ax>
|
|
exa_error:
|
|
|
|
endif ;DEAD_CODE -------------------------------------------------
|
|
|
|
cEnd ExitAppl
|
|
|
|
sEnd NRESCODE
|
|
|
|
|
|
sBegin CODE
|
|
assumes CS,CODE
|
|
;-----------------------------------------------------------------------;
|
|
; LoadApplSegment ;
|
|
; ;
|
|
; Load an APPL segment ;
|
|
; open file if not already open ;
|
|
; tests to make sure 1st segment is an APPL loader ;
|
|
; call the Apploader requesting segment be loaded ;
|
|
; NOTE : never call for first segment ;
|
|
; ;
|
|
; Arguments: ;
|
|
; parmW hexe (handle to exe header) ;
|
|
; parmW fh (file handle (may be -1)) ;
|
|
; parmW segno (segment #) ;
|
|
; ;
|
|
; Returns: ;
|
|
; NZ, AX != 0 => ok, AX = segment where loaded, DX = handle of seg;
|
|
; ;
|
|
; Error Returns: ;
|
|
; Z, AX == 0 => error ;
|
|
; ;
|
|
; Registers Preserved: ;
|
|
; ;
|
|
; Registers Destroyed: ;
|
|
; ;
|
|
; Calls: ;
|
|
; various ;
|
|
; ;
|
|
; History: ;
|
|
; ;
|
|
; Thu Jul 30, 1987 11:56:34a -by- Scott A. Randell [scottra] ;
|
|
; Created it ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
cProc LoadApplSegment,<NEAR,PUBLIC>,<si>
|
|
parmW hexe
|
|
parmW fh
|
|
parmW segno
|
|
localW myfh ;* private file handle
|
|
;* (if one shot open/close)
|
|
cBegin LoadApplSegment
|
|
|
|
mov es,hexe
|
|
mov myfh,-1 ;* try with what is open first
|
|
mov ax,fh
|
|
|
|
las_retry: ;* ax = file handle
|
|
mov si,es:[ne_segtab] ;* es:si => segtab
|
|
;* * first segment is the AppLoader
|
|
mov si,es:[si].ns_handle ;* handle
|
|
HtoS si ;* back to ring 1
|
|
mov es,si
|
|
;* * test to make sure that an APPL is there
|
|
cmp es:[magicAppl],magicApplCur ;* current version ?
|
|
;* (no backward compatibility)
|
|
jne las_error
|
|
|
|
;* * Try to reload with the handle Windows has (may be -1)
|
|
cCall es:[pfnReloadAppl], <hexe, ax, segno>
|
|
;* returns AX = segment
|
|
or ax,ax
|
|
jnz las_end ;* return AX != 0
|
|
;* * if the file handle was -1, open the file and try again
|
|
cmp myfh,-1
|
|
jne las_error ;* could not load with a file
|
|
;* * file is not open, open up temporary file (put handle in myfh)
|
|
mov es,hexe
|
|
mov dx,es:[ne_pfileinfo]
|
|
regptr esdx,es,dx
|
|
if SHARE_AWARE
|
|
mov bx,OF_REOPEN or OF_PROMPT or OF_CANCEL or OF_VERIFY + OF_SHARE_DENY_WRITE
|
|
else
|
|
mov bx,OF_REOPEN or OF_PROMPT or OF_CANCEL or OF_VERIFY
|
|
endif
|
|
push dx
|
|
Save <es>
|
|
cCall MyOpenFile,<esdx,esdx,bx>
|
|
pop dx
|
|
mov myfh,ax
|
|
cmp ax,-1
|
|
jne las_retry
|
|
|
|
las_error: ;* an error occured
|
|
;* * close file (if myfh != -1), then return error
|
|
debug_out "LoadApplSegment failed - better find out why!"
|
|
xor ax,ax
|
|
|
|
las_end: ;* ax = return value
|
|
mov bx,myfh
|
|
inc bx
|
|
jz las_no_temp_file
|
|
dec bx
|
|
push ax
|
|
mov ah,3Eh ;* close file handle
|
|
DOSCALL
|
|
pop ax
|
|
las_no_temp_file: ;* ax = return code
|
|
or ax,ax
|
|
cEnd LoadApplSegment
|
|
|
|
;-----------------------------------------------------------------------;
|
|
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; MySetOwner ;
|
|
; ;
|
|
; Private version of SetOwner for present/non-present selectors ;
|
|
; ;
|
|
; Arguments: ;
|
|
; selector = selector (present or non-present) ;
|
|
; owner = new owner field ;
|
|
; ;
|
|
; History: ;
|
|
; ;
|
|
; Mon 04-Dec-1989 10:03:25 -by- David N. Weise [davidw] ;
|
|
; Made it call set_discarded_sel_owner instead of set_sel_limit. ;
|
|
; ;
|
|
; Mon Jul 03 20:37:22 1989 created -by- Scott A. Randell [scottra] ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
cProc MySetOwner,<PUBLIC,FAR>, <SI, DI>
|
|
parmW selector
|
|
parmW owner
|
|
cBegin
|
|
cCall GlobalHandle,<selector>
|
|
or dx,dx ;* 0 => not present
|
|
jz set_owner_NP
|
|
;* * set owner for present selectors
|
|
cCall SetOwner,<selector, owner>
|
|
jmp short end_set_owner
|
|
|
|
set_owner_NP:
|
|
;* NP selectors store the owner in the segment limit
|
|
mov bx,selector
|
|
mov es,owner
|
|
call set_discarded_sel_owner
|
|
|
|
end_set_owner:
|
|
cEnd
|
|
|
|
sEnd CODE
|
|
|
|
endif ;!NO_APPLOADER (entire file)
|
|
|
|
end
|