|
|
TITLE LDUTIL - Loader support procedures
.xlist include kernel.inc include newexe.inc include tdb.inc include protect.inc .list
;externFP GetCurrentPDB
DataBegin
;externB Kernel_Flags ;externW AltfEEMS externW headTDB externW hExeHead ;externW pGlobalHeap ;externW MyCSDS externW topPDB externW cur_dos_pdb externW Win_PDB externW curTDB ;externW segSwapArea
DataEnd
externFP CallWEP
sBegin CODE assumes CS,CODE assumes DS,NOTHING assumes ES,NOTHING
externNP MyUpper externNP MyLock externNP LoadNRTable externNP LoadSegment externNP GetOwner externNP GetCachedFileHandle
if SDEBUG externNP DebugFreeSegment endif
externFP IGlobalAlloc externFP IGlobalFree ;externFP IGlobalLock externFP IGlobalUnfix externFP IGlobalHandle externFP GlobalFlags externFP FreeNRTable externFP Int21Handler
ifdef FE_SB ;declare it. externNP MyIsDBCSLeadByte ;Use near one as we are in the same seg endif
cProc SafeCall,<PUBLIC,FAR> parmD Addr cBegin call Addr cEnd
;-----------------------------------------------------------------------; ; GetExePtr ; ; ; ; Returns the exe header pointer for the passed handle. ; ; ; ; Arguments: ; ; parmW hinstance ; ; ; ; Returns: ; ; ; ; Error Returns: ; ; AX = 0 ; ; ; ; Registers Preserved: ; ; ; ; Registers Destroyed: ; ; ; ; Calls: ; ; ; ; History: ; ; ; ; Mon Aug 03, 1987 04:40:45p -by- David N. Weise [davidw] ; ; Rewrote it to work with expanded memory. Note that if the handle ; ; passed is truly bogus we could still catch a page fault under ; ; Win386. ; ;-----------------------------------------------------------------------;
assumes ds, nothing assumes es, nothing
cProc GetExePtr,<PUBLIC,FAR> parmW hinstance cBegin mov ax,hinstance test ax,GA_FIXED ; Passed a segment address? jz not_module mov es,ax cmp es:[ne_magic],NEMAGIC ; Yes, does it point to a Module? jz gxdone
not_module: SetKernelDS es mov cx,headTDB assumes es, nothing find_TDB: jcxz last_chance mov es,cx cmp ax,es:[TDB_module] jz found_it mov cx,es:[TDB_next] jmp find_TDB found_it: mov ax,es:[TDB_pModule] jmps gxdone
last_chance: ; The problem here is that USER cCall MyLock,<ax> ; KNOWS that hinstance is but or ax,ax ; the handle to his data segment. jz gxdone mov es,ax cmp es:[ne_magic],NEMAGIC je gxdone
cCall GetOwner,<ax> or ax,ax jz gxfail mov es,ax cmp es:[ne_magic],NEMAGIC je gxdone
; The owner,ax, is now a PDB. We gotta find the TDB SetKernelDS es mov cx,headTDB assumes es, nothing find_PDB: jcxz gxfail mov es,cx cmp ax,es:[TDB_PDB] jz found_PDB mov cx,es:[TDB_next] jmp find_PDB found_PDB: mov ax,es:[TDB_pModule] jmps gxdone
gxfail: if KDEBUG xor cx,cx kerror ERR_LDMODULE,<Invalid module handle>,cx,hinstance endif xor ax,ax gxdone: mov cx,ax
cEnd
;-----------------------------------------------------------------------; ; ; ; GetExpWinVer - return the expected Windows version for a given ; ; module handle ; ; ; ; Arguments: ; ; parmW hinstance ; ; ; ; Returns: ; ; AX = expected windows version ; ; DX = BOOL proportional font flag ; ; ; ; Error Returns: ; ; AX = 0 ; ; ; ; Registers Preserved: ; ; ; ; Registers Destroyed: ; ; ; ; Calls: ; ; ; ; History: ; ; ; ; Fri 06 Jan 1989 -- Written by Sankar. ; ; ; ;-----------------------------------------------------------------------;
assumes ds, nothing assumes es, nothing
cProc GetExpWinVer,<PUBLIC,FAR>, <si,di> parmW hInstance cBegin cCall GetExePtr,<hInstance> or ax,ax jz err_GetExpWinVer mov es,ax mov ax,es:[ne_expver] mov dx,es:[ne_flags] and dx,NEWINPROT ; error if offsets don't match our defines - In which case find the right ; offsets and changes the defines in mvdm\inc\tdb16.h
.erre (NE_LOWINVER_OFFSET EQ ne_expver) .erre (NE_HIWINVER_OFFSET EQ ne_flags)
err_GetExpWinVer:
cEnd
;-----------------------------------------------------------------------; ; MyAlloc ; ; ; ; Private interface to memory manager ; ; ; ; Arguments: ; ; parmW aflags ; ; parmW nsize ; ; parmW nelem ; ; ; ; Returns: ; ; ; ; Error Returns: ; ; AX = Handle ; ; DX = Seg Address ; ; ; ; Registers Preserved: ; ; DI,SI,DS ; ; ; ; Registers Destroyed: ; ; BX,CX,ES ; ; ; ; Calls: ; ; GlobalAlloc ; ; MyLock ; ; ; ; History: ; ; ; ; Wed Apr 08, 1987 06:22:57a -by- David N. Weise [davidw] ; ; Wrote it. ; ;-----------------------------------------------------------------------; assumes ds, nothing assumes es, nothing
cProc MyAllocLinear,<PUBLIC,NEAR> ; Same as MyAlloc, except for size parameter parmW aflags parmD dwBytes cBegin jmps MyAllocNBD cEnd
assumes ds, nothing assumes es, nothing
cProc MyAlloc,<PUBLIC,NEAR> parmW aflags parmD dwBytes ; parmW nsize ; parmW nelem cBegin xor dx,dx mov ax,seg_dwBytes ;nsize mov cx,off_dwBytes ;nelem jcxz ma3 ma2: shl ax,1 rcl dx,1 loop ma2 ma3: mov seg_dwBytes, dx mov off_dwBytes, ax MyAllocNBD: SetKernelDS es mov cx,aflags mov al,NSTYPE and al,cl ; al has SEGTYPE mov bx,NSDISCARD and bx,cx jz @F shr bx,1 shr bx,1 shr bx,1 shr bx,1 ; BX has GA_DISCARDABLE cmp al,NSCODE jne @F or bl,GA_DISCCODE ; Allocating discardable code @@:
cmp al,NSDATA jne @F and cx,NOT NSWINCODE ; undo Excel bogusness or bl,GA_DGROUP ; Allocating automatic data segment @@:
test cl,NSMOVE jz @F or bl,GA_MOVEABLE @@:
cmp al,NSTYPE jz @F or bh,GA_CODE_DATA @@:
cCall IGlobalAlloc,<bx,dwBytes> ;dxax>
assumes es, nothing push ax test al,GA_FIXED jnz @F cCall MyLock,<ax> @@: pop dx cEnd
; ; MyLock( hseg ) - Procedure to return the physical segment address of ; the passed handle. ; ;;;cProc MyLock,<PUBLIC,NEAR> ;;; parmW hseg ;;;cBegin ;;; cCall IGlobalHandle,<hseg> ;;; xchg dx,ax ;;;cEnd
;-----------------------------------------------------------------------; ; MyFree ; ; ; ; Frees a segment allocated by MyAlloc. ; ; ; ; Arguments: ; ; ; ; Returns: ; ; ; ; Error Returns: ; ; ; ; Registers Preserved: ; ; ; ; Registers Destroyed: ; ; ; ; Calls: ; ; ; ; History: ; ; ; ; Tue Dec 09, 1986 12:48:43p -by- David N. Weise [davidw] ; ; Added this nifty comment block. ; ;-----------------------------------------------------------------------;
assumes ds, nothing assumes es, nothing
cProc MyFree,<PUBLIC,NEAR> parmW hseg localW pseg cBegin mov bx,hseg or bx,bx jz mf3 mov ax,bx xor cx,cx test bl,GA_FIXED jnz mf0a
push bx cCall GlobalFlags,<bx> mov cx, ax xor ax, ax pop bx xchg ch, cl test cl, HE_DISCARDED jnz mf0a mov ax, bx HtoS ax
mf0a: if KDEBUG push cx endif mov pseg,ax or ax,ax jz mf1 mf0: if SDEBUG cCall DebugFreeSegment,<pseg,0> endif mf1: if KDEBUG pop cx or ch,ch jz mf2 mf1a: push cx cCall IGlobalUnfix,<hseg> ; Prevent RIP if freeing locked DS pop cx dec ch or ch,ch ; If still lock, do it again jnz mf1a endif mf2: cCall IGlobalFree,<hseg> mf3: cEnd
;-----------------------------------------------------------------------; ; EntProcAddress ; ; Returns the fixed address of a procedure. ; ; Entry: ; ; Returns: ; DX:AX = thunk for moveable ; DX:AX = procedure for fixed ; AX = constant, ES:BX => constant for absolutes ; Registers Destroyed: ; ; History: ; Wed 30-Nov-1988 19:39:05 -by- David N. Weise [davidw] ; ;-----------------------------------------------------------------------;
assumes ds, nothing assumes es, nothing
cProc EntProcAddress,<PUBLIC,NEAR>,<si,di> parmW hExe parmW entno if KDEBUG parmW bNoRip ; if 1 don't RIP for error, 0 -> do the RIP endif
cBegin mov es,hExe mov cx,entno and cx,7fffh ; clear ResidentName bit (#5108 donc) jcxz entfail dec cx mov si,es:[ne_enttab]
entloop: mov ax, es:[si.PM_entstart] cmp cx, ax ; Below this block? jb entfail ; yes, must be invalid! cmp cx, es:[si.PM_entend] ; Above this block? jae entnext ; yes, go to next block sub cx, ax ; Found the right block, get offset mov bx, cx shl cx, 1 add bx, cx add bx, cx ; bx = cx*5 lea si, [si+bx+size PM_entstruc] mov bx, si jmps gotent entnext: mov si, es:[si.PM_entnext] ; Next block or si, si jnz entloop jmps entfail
entfail: if KDEBUG cmp bNoRip,0 jnz dont_rip_here mov bx,entno krDebugOut <DEB_WARN or DEB_krLoadSeg>, "Invalid ordinal reference (##BX) to %ES1" ; kerror ERR_LDORD,<Invalid ordinal reference to >,es,bx dont_rip_here: endif xor dx,dx xor ax,ax jmps entdone
; Here if the current block has the entry we want
gotabs: add bx,pentoffset ; make ES:BX point to constant (SLIME!) mov dx,-1 ; make != 0 since abs might be! jmps gotent1 ; Offset is symbol value
gotent: xor ax, ax mov al, es:[bx].penttype ; Get segno/type field mov si,es:[bx].pentoffset cmp al,ENT_ABSSEG ; If segno field absoulute segment je gotabs ; Yes, have absolute symbol
cmp al, ENT_MOVEABLE je gotmoveable
.errnz 10 - SIZE NEW_SEG1 ; ax = segno push bx mov bx, es:[ne_segtab] ; see if really fixed mov cx, ax ; look up in seg table dec cx shl cx, 1 ; get segtable + (segno-1)*10 add bx, cx shl cx, 2 add bx, cx test es:[bx].ns_flags, NSMOVE + NSALLOCED pop bx jnz gotmoveable
mov cx,-1 ; Fixed, make sure it's loaded cCall LoadSegment,<es,ax,cx,cx> or ax,ax mov dx,ax jnz gotent1 jmp entfail
gotmoveable: xor ax,ax mov al,es:[bx].pentsegno ; Segment number dec ax shl ax,1 mov di,ax shl ax,2 add di,ax .errnz 10 - SIZE NEW_SEG1 add di,es:[ne_segtab]
mov dx,es:[di].ns_handle or dx, dx jnz ok mov ax, dx ; No handle, probably from an aborted jmps entdone ; LoadModule - just return 0:0 ok:
Handle_To_Sel dl
gotent1: mov ax,si
entdone: mov cx,ax or cx,dx cEnd
;-----------------------------------------------------------------------; ; FindOrdinal ; ; ; ; Searches the resident and non-resident name tables for a procedure ; ; name and return its corresponding entry ordinal. ; ; ; ; Arguments: ; ; parmW hExe ; ; parmD lpname pointer name, strings starts with length ; ; parmW fh file handle NOT to be discarded from cache ; ; ; ; Returns: ; ; AX = ordinal number ; ; ; ; Error Returns: ; ; ; ; Registers Preserved: ; ; ; ; Registers Destroyed: ; ; ; ; Calls: ; ; MyUpper ; ; LoadNRTable ; ; FreeNRTable ; ; ; ; History: ; ; ; ; Tue 09-May-1989 18:38:04 -by- David N. Weise [davidw] ; ; Added the batching if out of memory. ; ; ; ; Thu Sep 17, 1987 08:55:05p -by- David N. Weise [davidw] ; ; Added this nifty comment block and fixed it. ; ;-----------------------------------------------------------------------;
assumes ds, nothing assumes es, nothing
CLNRBUFFER equ 150
cProc FindOrdinal,<PUBLIC,NEAR>,<si,di> parmW hExe parmD lpname parmW fh
localD oNRTable ; if batching, continue here localV LoadNRbuffer,CLNRBUFFER ; if batching this is temp buffer cBegin xor ax,ax mov oNRTable.hi,ax mov oNRTable.lo,ax les si,lpname cmp byte ptr es:[si+1],'#' je foint
fonorm: push ds mov ds,hExe mov si,ds:[ne_restab] cld
foinit: xor ax,ax ; Skip module name or description lodsb add si,ax inc si inc si
foloop: lodsb ; get length of entry les di,lpname mov cx,ax jcxz fodone ; no more entries? cmp es:[di],al ; do lengths match? jne noteq inc di fo_find: mov al,es:[di] call MyUpper mov bl,ds:[si] inc si inc di cmp al,bl jne noteq1 loop fo_find ; repe cmpsb ; jne noteq lodsw ; get ordinal number! mov bx,ds pop ds cmp hExe,bx ; did we load the nrtable? jnz foexit_j jmp foexit1 foexit_j: jmp foexit
noteq1: dec cx noteq: add si,cx inc si inc si jmps foloop
; Here if pName points to string of the form: #nnnn
foint: lods byte ptr es:[si] ; nbytes = *pName++ mov cl,al xor ch,ch
dec cx ; ignore # inc si
xor ax,ax ; sum = 0 foint0: mov dx,ax lods byte ptr es:[si] ; c = *pName++ sub al,'0' ; if (!isdigit(c)) cmp al,9 ja fonorm ; treat like normal xor ah,ah mov bx,ax ; sum = (sum * 10) + (c - '0') mov al,10 mul dx add ax,bx loop foint0 jmp foexit1
fodone: mov bx,ds pop ds ;%out help me ; what was this line for? mov cx,oNRTable.hi cmp cx,oNRTable.lo jnz fo_batching cmp hExe,bx ; have we looked at NRTable yet? jne foexit
fo_batching: xor bx,bx mov ax,fh ;;; cmp ax,-1 ;;; jz no_file_handle
SetKernelDS ES ;;; mov dx, topPDB ;;; mov es, curTDB ;;; UnSetKernelDS es ;;; mov ax, es:[TDB_PDB] ;;; ;;; cmp dx, cur_dos_pdb ;;; jz @F ;;; mov bx,ax ;;;@@: mov bx, Win_PDB UnSetKernelDS
mov dx, -1 cCall GetCachedFileHandle,<hexe,ax,dx> no_file_handle: push bx lea cx,LoadNRbuffer mov dx,CLNRBUFFER cCall LoadNRTable,<hexe,ax,oNRTable,ss,cx,dx> if KDEBUG push es push di les di, [lpName] krDebugOut <DEB_TRACE or DEB_krLoadSeg>, " looking for @ES:DI" pop di pop es endif pop si or si,si jz @F ;;; push ax ;;; push bx ;;; mov bx,si ;;; mov ah,50h ;;; DOSCALL ;;; pop bx ;;; pop ax push es SetKernelDS ES mov Win_PDB, si pop es UnSetKernelDS ES @@: mov oNRTable.hi,cx mov oNRTable.lo,bx push ds mov ds,dx mov si,ax or ax,dx ; did we get a table? jz @F xor ax,ax jmp foloop @@: pop ds foexit: push ax mov ax,ne_nrestab cCall FreeNRTable,<hExe,ax> foexit0: pop ax foexit1:
;??? commented out 3/7/88 by rong ;??? we should put this back in once everyone has the new keyboard driver ;if KDEBUG ; or ax,ax ; jnz foexit2 ; les bx,lpname ; inc bx ; kerror ERR_LDNAME,<Invalid procedure name >,es,bx ; xor ax,ax ;foexit2: ;endif cEnd
; Search the list of new EXE headers for the passed executable file name ; (no path) ; ; this must be resident so we can search for modules in the file handle ; cache from the int 21 handler -- craigc ;
cProc ResidentFindExeFile,<PUBLIC,FAR>,<ds,si,di> parmD pname cBegin SetKernelDS
mov ax,hExeHead ffloop: or ax,ax jz ffdone mov es,ax mov di,es:[ne_pfileinfo] or di,di jz ffnext
; ; Double Byte Character is not able to search from the end of string, ; so this function must search from the top of string. ; ifdef FE_SB lea si,[di.opFile] ; get address of file name mov cl,es:[di.opLen] ; get structure length xor ch,ch add cx,di mov di,cx ; save end address sub cx,si ; get length of file name mov bx,si ; save top address of file name cld delineator_loop: lods byte ptr es:[si] call MyIsDBCSLeadByte jc delineator_notlead ; if not DBCS lead byte dec cx jcxz delineator_next inc si loop delineator_loop jmp delineator_next delineator_notlead: cmp al,"\" jz found_delineator cmp al,":" jz found_delineator loop delineator_loop jmp delineator_next found_delineator: mov bx,si ; save delineator address loop delineator_loop delineator_next: xchg bx,di ; set address of file name to di sub bx,di ; get lenfth of file name else mov si,di xor cx,cx mov cl,es:[di] add si,cx dec si std xor bx,bx delineator_loop: ; look for beginning of name lods byte ptr es:[si] cmp al,"\" jz found_delineator cmp al,":" jz found_delineator inc bx loop delineator_loop dec si found_delineator: ; ES:SI -> before name mov di,si inc di inc di endif
lds si,pname UnSetKernelDS mov cx,bx cld repe cmpsb mov ax,es je ffdone ffnext: mov ax,word ptr es:[ne_pnextexe] jmp ffloop ffdone: cEnd
sEnd CODE
externFP FarLoadSegment
sBegin NRESCODE assumes CS,NRESCODE assumes DS,NOTHING assumes ES,NOTHING
externNP DelModule externNP MapDStoDATA
cProc FindExeFile,<PUBLIC,NEAR> parmD pFile cBegin cCall ResidentFindExeFile, <pFile> cEnd
; Search the list of new EXE headers for the passed executable name
cProc FindExeInfo,<PUBLIC,NEAR>,<ds,si,di> parmD pname parmW nchars cBegin
cCall MapDStoDATA ReSetKernelDS
mov bx,nchars mov ax,hExeHead feloop: or ax,ax jz fedone mov es,ax mov di,es:[ne_restab] cmp es:[di],bl jne fenext inc di lds si,pname UnSetKernelDS mov cx,bx repe cmpsb je fedone fenext: mov ax,word ptr es:[ne_pnextexe] jmp feloop fedone: cEnd
cProc FarFindExeInfo,<PUBLIC,FAR> parmD pname parmW nchars cBegin cCall FindExeInfo,<pname,nchars> cEnd
; ; IncExeUsage( hExe ) - procedure to increment the usage count of this ; EXE header. Indirectly increments the usage count of all the EXE ; headers it points to. ; cProc IncExeUsage,<PUBLIC,NEAR>,<ax,di> parmW hexe cBegin mov cx,hexe jcxz iexj mov es,cx cmp es:[ne_magic],NEMAGIC jne iexj test es:[ne_usage],8000h jz iego iexj: krDebugOut <DEB_ERROR or DEB_KRLOADMOD>, "IncExeUsage(#ES) not DLL" jmp iex iego:
cmp es:[ne_usage], 4000h jb OKusage krDebugOut DEB_FERROR, "IncExeUsage: ne_usage overflow" OKusage:
; ; Save time and space by saving stuff on stack ; rather than recursing. ;
or es:[ne_usage], 8000h NextExe0: or es:[ne_usage], 4000h ; Mark node visited inc es:[ne_usage] ;if kdebug ; push ax ; mov ax, es:[ne_usage] ; krDebugOut <DEB_TRACE or DEB_krLoadMod>, "IncExeUsage(%ES0) #ax" ; pop ax ;endif mov cx,es:[ne_cmod] jcxz NoDeps0 mov di,es:[ne_modtab] ieloop: push es cmp word ptr es:[di], 0 je ieloop1 lar ax, es:[di] ; Make sure valid selector jnz ieloop1 mov es, es:[di] cmp es:[ne_magic],NEMAGIC jne ieloop1 test es:[ne_usage], 0C000h jnz ieloop1 push cx push di ; Fake recursion jmp NextExe0 NextExeDone0: ; Return from fake recursion pop di pop cx ieloop1: pop es add di,2 loop ieloop
NoDeps0: mov cx, es cmp cx, hExe jne NextExeDone0
NextExe1: and es:[ne_usage], NOT 4000h ; Mark node visited mov cx,es:[ne_cmod] jcxz NoDeps1 mov di,es:[ne_modtab] UnMarkLoop: push es cmp word ptr es:[di], 0 je UnMarkLoop1 lar ax, es:[di] ; Make sure valid selector jnz UnMarkLoop1 mov es, es:[di] cmp es:[ne_magic],NEMAGIC jne UnMarkLoop1 test es:[ne_usage], 08000h jnz UnMarkLoop1 test es:[ne_usage], 04000h jz UnMarkLoop1 push cx push di ; Fake recursion jmp NextExe1 NextExeDone1: ; Return from fake recursion pop di pop cx UnMarkLoop1: pop es add di,2 loop UnMarkLoop
NoDeps1: mov cx, es cmp cx, hExe jne NextExeDone1
xor es:[ne_usage], 8000h iex: cEnd
;-----------------------------------------------------------------------; ; DecExeUsage ; ; ; ; Decrements the usage count of the given EXE header. Indirectly ; ; decrements the usage count of all the EXE headers it points to. ; ; ; ; Arguments: ; ; parmW hexe ; ; ; ; Returns: ; ; ZF = 1 if usage count is now zero. ; ; ; ; Error Returns: ; ; ; ; Registers Preserved: ; ; DI,SI,DS ; ; ; ; Registers Destroyed: ; ; AX,BX,CX,DX,ES ; ; ; ; Calls: ; ; DecExeUsage ; ; DelModule ; ; ; ; History: ; ; ; ; Mon Sep 21, 1987 01:21:00p -by- David N. Weise [davidw] ; ; Added this nifty comment block. ; ;-----------------------------------------------------------------------;
cProc DecExeUsage,<PUBLIC,NEAR>,<ds,di,si> parmW hexe cBegin call MapDStoDATA ReSetKernelDS
xor si,si mov cx,hexe xor ax,ax jcxz dexj mov es,cx cmp es:[si].ne_magic,NEMAGIC jne dexj test es:[si].ne_usage,8000h jz dego dexj: krDebugOut <DEB_ERROR or DEB_KRLOADMOD>, "DecExeUsage(#ES) not DLL" jmp dex dego:
; ; Save time and space by saving stuff on stack ; rather than recursing. ;
dec es:[si].ne_usage or es:[si].ne_usage, 8000h ;if kdebug ; push ax ; mov ax, es:[si].ne_usage ; krDebugOut <DEB_TRACE or DEB_krLoadMod>, "DecExeUsage(%ES0) #ax" ; pop ax ;endif NextExe2: or es:[si].ne_usage, 4000h ; Mark node visited mov cx,es:[si].ne_cmod jcxz NoDeps2 mov di,es:[si].ne_modtab MarkLoop2: push es cmp si, es:[di] je MarkLoop3 lar ax, es:[di] ; Make sure valid selector jnz MarkLoop3 mov es, es:[di] cmp es:[si].ne_magic,NEMAGIC jne MarkLoop3 test es:[si].ne_usage, 0C000h jnz MarkLoop3 push cx push di ; Fake recursion jmp NextExe2 NextExeDone2: ; Return from fake recursion pop di pop cx MarkLoop3: pop es add di,2 loop MarkLoop2
NoDeps2: mov cx, es cmp cx, hExe jne NextExeDone2
xor cx, cx push cx ; End of list of Exes to delete mov di, hExeHead ; Scan Exes once to dec them scan_exes: or di, di jz de_done mov es, di mov di, es:[si].ne_pnextexe test es:[si].ne_usage, 4000h jz scan_exes and es:[si].ne_usage, NOT 4000h ; Remove the mark test es:[si].ne_usage, 8000h ; Skip this one? jnz scan_exes ; krDebugOut <DEB_TRACE or DEB_krLoadMod>, "DecExeUsage dependent %ES0" dec es:[si].ne_usage jnz scan_exes push es ; We will delete this one jmps scan_exes
de_done: ; Call WEP each module before mov bx, sp ; we free any modules de_done0: mov cx, ss:[bx] add bx, 2 jcxz de_done1 push bx cCall CallWEP, <cx, 0> pop bx jmps de_done0
de_done1: pop cx ; Get next module to delete jcxz all_deleted cCall DelModule,<cx> ; Delete him jmps de_done1
all_deleted: mov es, hExe and es:[si].ne_usage,NOT 0C000h dex: cEnd
; ; StartProcAddress( hExe ) - procedure to return the fixed address of ; a new EXE start procedure ; cProc StartProcAddress,<PUBLIC,NEAR>,<di> parmW hexe parmW fh cBegin mov es,hexe mov di,ne_csip xor dx,dx mov ax,es:[di+2] or ax,ax jz sp1 mov di,es:[di] cCall FarLoadSegment,<es,ax,fh,fh> jcxz sp1 mov ax,di ; DX:AX is start address of module sp1: ; (DX is really a handle) mov cx,ax or cx,dx cEnd
; GetStackPtr - returns the initial SS:SP for a module. ; cProc GetStackPtr,<PUBLIC,NEAR>,<si> parmW hExe cBegin mov es,hExe if KDEBUG cmp es:[ne_sssp].sel,0 jnz @F mov cx,ne_sssp fkerror 0,<Invalid stack segment>,es,cx @@: endif cmp es:[ne_sssp].off,0 jne re3 mov dx,es:[ne_stack] mov bx,es:[ne_pautodata] or bx,bx jz re2 add dx,es:[bx].ns_minalloc re2: and dx,0FFFEh ; Word aligned stack mov word ptr es:[ne_sssp],dx
re3: mov dx,es:[ne_sssp].sel mov ax,es:[ne_sssp].off push ax mov cx,-1 cCall FarLoadSegment,<es,dx,cx,cx> pop ax ; Handle in DX and offset in AX cEnd
; ; GetInstance( hExe ) - Procedure to return the instance handle for ; the current automatic data segment associated with the passed exe ; cProc GetInstance,<PUBLIC,NEAR> parmW hexe cBegin mov es,hexe mov ax,es:[ne_flags] test ax,NEINST+NESOLO mov ax,es jz gidone mov bx,es:[ne_pautodata] or bx,bx jz gidone mov ax,es:[bx].ns_handle gidone: mov cx,ax cEnd
sEnd NRESCODE
end
|