windows-nt/Source/XPSP1/NT/base/mvdm/wow16/kernel31/module.asm
2020-09-26 16:20:57 +08:00

558 lines
13 KiB
NASM

.xlist
include kernel.inc
include newexe.inc
include tdb.inc
.list
;externFP GlobalCompact
externFP GlobalFreeAll
externFP GetExePtr
externFP FarMyFree
externFP Far_genter
externFP FlushCachedFileHandle
externFP GetProcAddress
externFP FarUnlinkObject
externFP CallWEP
externFP lstrcpy
if SDEBUG
externFP FarDebugDelModule
endif
DataBegin
externB fBooting
;externW EMScurPID
externW curTDB
externW loadTDB
externW headTDB
externW hExeHead
externW pGlobalHeap
externW MyCSDS
externD pSignalProc
ifdef WOW
externW hWinnetDriver
externW hUser
endif ; WOW
DataEnd
sBegin CODE
assumes CS,CODE
assumes DS,NOTHING
assumes ES,NOTHING
;-----------------------------------------------------------------------;
; UnlinkObject ;
; ;
; Removes an object from a singly linked list of objects. ;
; ;
; Arguments: ;
; CS:BX = head of chain ;
; ES = object to delete ;
; DX = offset of next pointer in object ;
; ;
; Returns: ;
; AX = deleted object ;
; ;
; Error Returns: ;
; none ;
; ;
; Registers Preserved: ;
; BX,DI,SI,BP,DS ;
; ;
; Registers Destroyed: ;
; CX,DX,ES ;
; ;
; Calls: ;
; ;
; History: ;
; ;
; Mon Sep 29, 1986 11:29:32a -by- Charles Whitmer [chuckwh] ;
; Wrote it to remove this code from the three different places where ;
; it was included inline. ;
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc UnlinkObject,<PUBLIC,NEAR>
cBegin nogen
push di
mov di,dx
; keep DX = next object
mov dx,es:[di]
; see if the object is at the head
push ds
SetKernelDS
mov cx,ds:[bx] ; start CX at head
mov ax,es ; AX = object to delete
cmp ax,cx
jnz not_at_head
mov ds:[bx],dx
pop ds
UnSetKernelDS
jmp short unlink_done
not_at_head:
pop ds
UnSetKernelDS
; run down the chain looking for the object
unlink_loop:
jcxz unlink_done
mov es,cx
mov cx,es:[di]
cmp ax,cx
jnz unlink_loop
mov es:[di],dx
unlink_done:
pop di
ret
cEnd nogen
sEnd CODE
sBegin NRESCODE
assumes CS,NRESCODE
assumes DS,NOTHING
assumes ES,NOTHING
externNP MapDStoDATA
externNP DecExeUsage
externNP FlushPatchAppCache
IFNDEF NO_APPLOADER
externNP ExitAppl
ENDIF ;!NO_APPLOADER
;-----------------------------------------------------------------------;
; KillLibraries ;
; ;
; Scans the list of EXEs looking for Libraries. For all Libraries ;
; it looks for a procedure called 'WEP'. If found, WEP is called with ;
; fSystemExit set. ;
; ;
; Arguments: ;
; None ;
; ;
; Returns: ;
; None ;
; ;
; Error Returns: ;
; none ;
; ;
; Registers Preserved: ;
; DI,SI,BP,DS ;
; ;
; Registers Destroyed: ;
; BX,CX,DX,ES ;
; ;
; Calls: ;
; GetProcAddress ;
; ;
; History: ;
; ;
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc KillLibraries,<PUBLIC,FAR>,<DS>
localW hExe
cBegin
SetKernelDSNRes
mov cx, hExeHead
kl_NextExe:
UnSetKernelDS
mov ds, cx ; This skips first module (kernel)
mov cx, ds:[ne_pnextexe]
jcxz kl_done
push cx
cCall CallWEP, <cx, 1> ; Call for any module (call is fast)
pop cx
jmp kl_NextExe
kl_done:
cEnd
;-----------------------------------------------------------------------;
; AddModule ;
; ;
; Adds a module to the end of the list of modules. ;
; ;
; Arguments: ;
; parmW hExe seg of module to add ;
; ;
; Returns: ;
; AX != 0 if successful ;
; ;
; Error Returns: ;
; AX == 0 if error detected ;
; ;
; Registers Preserved: ;
; DI,SI,DS ;
; ;
; Registers Destroyed: ;
; AX,BX,CX,DX,ES ;
; ;
; Calls: ;
; GlobalCompact ;
; CalcMaxNRSeg ;
; FarRedo_library_entries ;
; ;
; History: ;
; Wed 24-Jul-1991 -by- Don Corbitt [donc] ;
; Finish removal of Real mode code, dead code. Remove module from ;
; list if insufficient memory. Directly set DS on entry. ;
; ;
; Thu 23-Mar-1989 23:00:40 -by- David N. Weise [davidw] ;
; Made tasks and libraries be separate on the module chain. ;
; ;
; Thu Feb 25, 1988 08:00:00a -by- Tim Halvorsen [iris] ;
; Check new error return from Redo_library_entries, returned when ;
; we totally run out of space for another library's entry table ;
; in EMS (the entry table is for ALL tasks, not just this task). ;
; Fix comments above to reflect correct returns from this routine. ;
; ;
; Wed May 06, 1987 00:07:20a -by- David N. Weise [davidw] ;
; Added support for EMS and library entrys. ;
; ;
; Thu Dec 11, 1986 12:10:26p -by- David N. Weise [davidw] ;
; Added this nifty comment block, and made it set calculate and set ;
; ne_swaparea. ;
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc AddModule,<PUBLIC,NEAR>,<ds>
parmW hExe
localW hLast ; last module in current list
cBegin
SetKernelDSNRes
xor bx,bx
mov cx,hExeHead
am0: mov es,cx ; find end of linked list of exe's
mov cx,es:[bx].ne_pnextexe
or cx, cx
jnz am0
; Here to add a module to the end of the chain. BX == 0.
mov hLast, es ; so we can remove hExe on failure
mov ax,hExe
mov es:[bx].ne_pnextexe,ax
mov es,ax
mov es:[bx].ne_pnextexe,bx
xor bx,bx
am_done:
mov ax,hExe
am_exit:
cEnd
;-----------------------------------------------------------------------;
; DelModule ;
; ;
; Deletes a module from the list of modules. ;
; ;
; Arguments: ;
; parmW hExe seg of module to delete ;
; ;
; Returns: ;
; AX = 0 ;
; ;
; Error Returns: ;
; ;
; Registers Preserved: ;
; DI,SI,DS ;
; ;
; Registers Destroyed: ;
; AX,BX,CX,DX,ES ;
; ;
; Calls: ;
; FarUnlinkObject ;
; GlobalFreeAll ;
; CalcMaxNRSeg ;
; EMSDelModule ;
; ;
; History: ;
; ;
; Wed May 06, 1987 00:07:20a -by- David N. Weise [davidw] ;
; Added support for EMS and library entrys. ;
; ;
; Tue May 05, 1987 10:36:29p -by- David N. Weise [davidw] ;
; Added this nifty comment block. ;
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc DelModule,<PUBLIC,NEAR>,<ds,di>
parmW pExe
cBegin
SetKernelDSNRes
if SDEBUG
mov es, pExe
call FarDebugDelModule ; is ES preserved?
endif
cCall CallWEP,<pExe,0>
mov es, pExe
test es:[ne_flags],NENOTP
jz dm_not_a_lib
; call user to clean up any stuff
test es:[ne_flags],NEPROT ; OS/2 app? is this necessary???
jnz no_user_yet
cmp pSignalProc.sel,0
jz no_user_yet
xor ax,ax
mov bx,80h
mov es:[ne_usage],1
push es
cCall pSignalProc,<pExe,bx,ax,ax,ax>
pop es
mov es:[ne_usage],0
no_user_yet:
dm_not_a_lib:
; Following code moved here
; from FreeModule 1/18/89
mov es,pExe
mov bx,es:[ne_pautodata]
or bx,bx
jz fm00
cCall FarMyFree,<es:[bx].ns_handle> ; Free DS separately to free thunks
fm00:
IFNDEF NO_APPLOADER
mov es,pExe
test es:[ne_flags],NEAPPLOADER
jz normal_unload
;* * special unload for AppLoader
cCall ExitAppl,<es>
normal_unload:
ENDIF ;!NO_APPLOADER ; END code from FreeModule
cCall FlushPatchAppCache, <pExe> ; Flush out Module Patch cache
cCall FlushCachedFileHandle,<pExe> ; Flush out of file handle cache
cCall Far_genter ; so we don't interfere with lrusweep
SetKernelDSNRes
mov es,pExe
mov dx,ne_pnextexe
mov bx,dataOffset hExeHead
call FarUnlinkObject
mov es,pGlobalHeap
xor di,di
dec es:[di].gi_lrulock
mov es,pExe ; Make sure no one mistakes this for
mov es:[di].ne_magic,di ; an exe header anymore.
cCall GlobalFreeAll,<pExe>
xor ax,ax
cEnd
;-----------------------------------------------------------------------;
; FreeModule ;
; ;
; Deletes the given module from the system. First it decs the usage ;
; count checking to see if this is the last instance, ( this may ;
; indirectly free other modules). If this is the last instance then ;
; it frees the automatic data segment to free any thunks associated ;
; with this module. Then the module is deleted. If this was not the ;
; last instance then the ns_handle for the automatic data seg may have ;
; to be updated. ;
; ;
; Arguments: ;
; parmW hInstance ;
; ;
; Returns: ;
; ;
; Error Returns: ;
; ;
; Registers Preserved: ;
; ;
; Registers Destroyed: ;
; ;
; Calls: ;
; ;
; History: ;
; ;
; Mon 03-Apr-1989 22:22:01 -by- David N. Weise [davidw] ;
; Removed the GlobalCompact at the end of this routine. ;
; ;
; Fri Jul 10, 1987 11:54:51p -by- David N. Weise [davidw] ;
; Added this nifty comment block. ;
;-----------------------------------------------------------------------;
labelFP <PUBLIC, IFreeLibrary>
assumes ds,nothing
assumes es,nothing
cProc IFreeModule,<PUBLIC,FAR>,<si,di>
parmW hInstance
cBegin
cCall GetExePtr,<hInstance> ; Get exe header address
or ax,ax
jz fmexit1
mov si,ax
ifdef WOW
; we can't allow anybody except user.exe take the ref count for 16-bit net
; driver down to 0 (see pNetInfo in user16\net.c winnet.asm) bug #393078
mov es,si
cmp es:[ne_usage],1
jnz fmNoProb ; if usage ref count isn't 1 -- no worries
mov dx,word ptr [bp+4] ; selector of calling module
; See if it is user.exe freeing the net driver.
cCall <far ptr IsOKToFreeThis>,<dx,ax>
or ax,ax ; Will be 0 if & only if the module being freed is
; 16-bit net driver & the module freeing it is NOT
; user.exe. Otherwise ax will = si
jz fmexit1 ; lie & say we freed 16-bit net driver & return ref count = 0
fmNoProb:
endif ; WOW
cCall DecExeUsage,<si> ; Decrement usage count
jnz fmfree ; If non-zero, then just free inst.
ifdef WOW
; Word Perfect v5.2 needs DX to contain a number >= 0x17 inorder
; to print properly. Since on Win 3.1, the DX value came from
; this point, lets save it for them. (On Win 3,1, the printer
; driver was being free'd here, but not deleted, GDI or spooler
; still has it open).
push dx
endif
cCall DelModule,<si> ; If zero, free entire module
ifdef WOW
pop dx
endif
fmexit1:
jmps fmexit
fmfree:
mov es,si
test byte ptr es:[ne_flags],NEINST
jz fmexit ; All done if not a multiple inst
mov bx,es:[ne_pautodata]
push es:[bx].ns_handle
cCall FarMyFree,<hInstance> ; Free instance
pop dx
cmp dx,hInstance ; Did we free current instance?
jne fmexit ; No, then continue
cCall MapDStoDATA
ReSetKernelDS
xor ax,ax
xor bx,bx
mov cx,headTDB ; Yes, search TDBs looking for
UnSetKernelDS
fm0: jcxz fm1 ; another instance handle
mov es,cx
cmp si,es:[bx].TDB_pModule
mov cx,es:[bx].TDB_next
jnz fm0
mov ax,es:[bx].TDB_module
cmp ax,hInstance ; Is this the instance we're quitting?
jz fm0
fm1: mov es,si
mov bx,es:[bx].ne_pautodata
mov es:[bx].ns_handle,ax ; Remember handle of data seg
fmexit:
cEnd
sEnd NRESCODE
ifdef WOW
sBegin CODE
assumes CS,CODE
assumes DS,NOTHING
assumes ES,NOTHING
;
; called by user.exe\net.c\LW_InitNetInfo()
;
; Arguments:
; parmW hInstNetDrv - hInstance of net driver library loaded by user.exe
;
; Returns:
; nothing
;
cProc TellKrnlWhoNetDrvIs, <PUBLIC,FAR>,<si,di>
parmW hInstNetDrv
cBegin
SetKernelDS
cCall getexeptr,<hInstNetDrv>
mov hWinnetDriver,ax ; save hMod of net driver
UnSetKernelDS
cEnd
;
; Should only be called if the ref (usage) count for module being freed is 1.
; (ie. about to go to zero)
;
; Arguments:
; parmW modsel - selector of code calling FreeModule
; parmW hModFree - hModule of module being freed
;
; Returns:
; 0 if & only if the module being freed is hWinnetDriver as set by user.exe
; AND the module calling FreeModule is NOT user.exe
; Otherwise: the hMod of the module being freed
;
cProc IsOKToFreeThis, <PRIVATE,FAR>,<si,di>
parmW modsel
parmW hModFree
cBegin
SetKernelDS
mov ax,hModFree
cmp ax,hWinnetDriver ; is hMod of the net driver module?
jnz IOKExit ; Exit if not -- no worries
; Danger! hMod being freed is the net driver
cCall getexeptr,<modsel> ; get hMod of caller
cmp ax,hUser ; See if caller is user.exe
jz IOK2FT1 ; yep, that's OK
xor ax,ax ; ret 0 so we don't free the net driver
jmp IOKExit
IOK2FT1:
mov ax,hModFree
IOKExit:
UnSetKernelDS
cEnd
endif ; WOW
sEnd CODE
end