1971 lines
43 KiB
NASM
1971 lines
43 KiB
NASM
page ,132
|
|
title TASK - task create/destroy procedures
|
|
.xlist
|
|
include kernel.inc
|
|
include tdb.inc
|
|
include pdb.inc
|
|
include eems.inc
|
|
include newexe.inc
|
|
include dbgsvc.inc
|
|
include bop.inc
|
|
.list
|
|
|
|
outd macro msg,n
|
|
%out msg n
|
|
endm
|
|
if2
|
|
; outd <TDBsize =>,%TDBsize
|
|
endif
|
|
|
|
externW pStackBot
|
|
externW pStackMin
|
|
externW pStackTop
|
|
|
|
if ROM
|
|
externFP FarIsROMObject
|
|
endif
|
|
|
|
externFP SafeCall
|
|
externFP BuildPDB
|
|
externFP LockSegment
|
|
externFP UnlockSegment
|
|
;externFP Yield
|
|
externFP LocalInit
|
|
externFP GlobalAlloc
|
|
externFP GlobalFree
|
|
;externFP GlobalLock
|
|
externFP GlobalUnLock
|
|
externFP GlobalCompact
|
|
externFP IGlobalHandle
|
|
externFP GlobalLRUOldest
|
|
externFP AllocDStoCSAlias
|
|
;;;externFP FarMyLock
|
|
externFP FarSetOwner
|
|
externFP default_sig_handler
|
|
externFP CVW_Hack
|
|
externFP GlobalDOSAlloc
|
|
externFP GlobalDOSFree
|
|
externFP AllocSelector
|
|
externFP LongPtrAdd
|
|
externFP MyFarDebugCall
|
|
externFP Int21Handler
|
|
if PMODE32
|
|
externFP far_get_arena_pointer32
|
|
externFP FarAssociateSelector32
|
|
externFP KRebootInit
|
|
else
|
|
externFP far_get_arena_pointer
|
|
externFP FarAssociateSelector
|
|
endif
|
|
|
|
if KDEBUG
|
|
externFP SetupAllocBreak
|
|
endif
|
|
|
|
ifdef WOW
|
|
externFP SetAppCompatFlags
|
|
externFP WowReserveHtask
|
|
externFP FreeSelector
|
|
externFP WowPassEnvironment
|
|
externFP ExitCall
|
|
endif
|
|
|
|
DataBegin
|
|
|
|
;externB fEMM
|
|
externB fBooting
|
|
externB kernel_flags
|
|
externB num_tasks
|
|
;externW hexehead
|
|
externW pGlobalHeap
|
|
externW curTDB
|
|
externW loadTDB
|
|
externW headTDB
|
|
externW headPDB
|
|
externW topPDB
|
|
externW cur_DOS_PDB
|
|
externW Win_PDB
|
|
;if PMODE32
|
|
;externW ArenaSel
|
|
;endif
|
|
externW MyCSAlias
|
|
externD pUserInitDone
|
|
externD ptrace_app_entry
|
|
externD ptrace_DLL_entry
|
|
externD pSignalProc
|
|
|
|
if KDEBUG
|
|
globalW allocTask,0
|
|
globalD allocCount,0
|
|
globalD allocBreak,0
|
|
globalB allocModName,0,8
|
|
endif ;KDEBUG
|
|
|
|
if ROM
|
|
externD prevInt00proc
|
|
endif
|
|
|
|
ifdef WOW
|
|
externD FastBop
|
|
externW DebugWOW
|
|
endif
|
|
|
|
DataEnd
|
|
|
|
sBegin CODE
|
|
assumes CS,CODE
|
|
assumes DS,NOTHING
|
|
assumes ES,NOTHING
|
|
|
|
ife ROM
|
|
externD prevInt00proc
|
|
endif
|
|
|
|
externNP SaveState
|
|
externNP UnlinkObject
|
|
externNP genter
|
|
externNP gleave
|
|
|
|
nullcomline DB 0,0Dh
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; GetCurrentTask ;
|
|
; ;
|
|
; Returns the current task. ;
|
|
; ;
|
|
; Arguments: ;
|
|
; none ;
|
|
; ;
|
|
; Returns: ;
|
|
; AX = curTDB ;
|
|
; DX = headTDB ;
|
|
; ;
|
|
; Error Returns: ;
|
|
; ;
|
|
; Registers Preserved: ;
|
|
; all ;
|
|
; ;
|
|
; Registers Destroyed: ;
|
|
; ;
|
|
; Calls: ;
|
|
; nothing ;
|
|
; ;
|
|
; History: ;
|
|
; ;
|
|
; Sun Feb 01, 1987 07:45:40p -by- David N. Weise [davidw] ;
|
|
; Added this nifty comment block. ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc GetCurrentTask,<PUBLIC,FAR>
|
|
cBegin nogen
|
|
push es
|
|
SetKernelDS ES
|
|
mov ax,curTDB
|
|
mov dx,headTDB
|
|
; mov bx,codeOffset headTDB
|
|
; mov cx,codeOffset curTDB
|
|
pop es
|
|
ret
|
|
assumes es,nothing
|
|
cEnd nogen
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; InsertTask ;
|
|
; ;
|
|
; Inserts a task into the task list. ;
|
|
; ;
|
|
; Arguments: ;
|
|
; parmW hTask ;
|
|
; ;
|
|
; Returns: ;
|
|
; ;
|
|
; Error Returns: ;
|
|
; ;
|
|
; Registers Preserved: ;
|
|
; CX,DX,DI,SI,DS ;
|
|
; ;
|
|
; Registers Destroyed: ;
|
|
; AX,BX,ES ;
|
|
; ;
|
|
; Calls: ;
|
|
; nothing ;
|
|
; ;
|
|
; History: ;
|
|
; ;
|
|
; Sun Feb 01, 1987 09:41:24p -by- David N. Weise [davidw] ;
|
|
; Added this nifty comment block. ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc InsertTask,<PUBLIC,NEAR>,<ds>
|
|
parmW hTask
|
|
cBegin
|
|
mov es,hTask ; get task handle
|
|
SetKernelDS
|
|
mov ax,headTDB ; get head of task list
|
|
UnSetKernelDS
|
|
or ax,ax ; anybody here?
|
|
jz ins1 ; no, just do trivial case
|
|
|
|
ins0: mov ds,ax ; point to head TDB
|
|
mov bl,es:[TDB_priority] ; get insert priority
|
|
cmp bl,ds:[TDB_priority] ; is it less than head task?
|
|
jg ins2 ; no, insert elsewhere
|
|
mov es:[TDB_next],ax
|
|
ins1: SetKernelDS
|
|
mov headTDB,es
|
|
UnSetKernelDS
|
|
jmps ins4
|
|
|
|
ins2: mov ds,ax ; save segment of previous TDB
|
|
mov ax,ds:[TDB_next] ; get segment of next tdb
|
|
or ax,ax ; if zero, insert now
|
|
jz ins3
|
|
mov es,ax ; point to new TDB
|
|
cmp bl,es:[TDB_priority]
|
|
jg ins2
|
|
ins3: mov es,hTask
|
|
mov ds:[TDB_next],es
|
|
mov es:[TDB_next],ax
|
|
ins4:
|
|
cEnd
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; DeleteTask ;
|
|
; ;
|
|
; Deletes a task from the task list. ;
|
|
; ;
|
|
; Arguments: ;
|
|
; parmW hTask ;
|
|
; ;
|
|
; Returns: ;
|
|
; AX = hTask ;
|
|
; ;
|
|
; Error Returns: ;
|
|
; ;
|
|
; Registers Preserved: ;
|
|
; ;
|
|
; Registers Destroyed: ;
|
|
; ;
|
|
; Calls: ;
|
|
; UnlinkObject ;
|
|
; ;
|
|
; History: ;
|
|
; ;
|
|
; Sun Feb 01, 1987 09:41:24p -by- David N. Weise [davidw] ;
|
|
; Added this nifty comment block. ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc DeleteTask,<PUBLIC,NEAR>
|
|
parmW hTask
|
|
cBegin
|
|
mov es,hTask
|
|
mov bx,dataOffset headTDB
|
|
mov dx,TDB_next
|
|
call UnlinkObject ; returns AX = hTask
|
|
cEnd
|
|
|
|
|
|
cProc FarCreateTask,<PUBLIC,FAR> ; Called from CreateTask
|
|
; parmW fPrev ; Calls several 'near' CODE funcs
|
|
cBegin
|
|
cCall SaveState,<ds>
|
|
SetKernelDS es
|
|
mov loadTDB,ds
|
|
cCall InsertTask,<ds>
|
|
clc
|
|
cEnd
|
|
|
|
if KDEBUG
|
|
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; CheckGAllocBreak
|
|
;
|
|
; Checks to see if the allocation break count has been reached.
|
|
; Returns CARRY SET if the allocation should fail, CLEAR otherwise.
|
|
; Increments the allocation count.
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
|
|
LabelNP <PUBLIC, CheckGAllocBreak>
|
|
errn$ CheckLAllocBreak
|
|
|
|
cProc CheckLAllocBreak,<PUBLIC,NEAR>,<DS,AX>
|
|
cBegin
|
|
SetKernelDS
|
|
assumes ds,DATA
|
|
|
|
mov ax,allocTask ; if allocTask != curTDB, exit.
|
|
or ax,ax ; curTDB may be NULL during boot.
|
|
jz cab_nofail
|
|
cmp ax,curTDB
|
|
jnz cab_nofail
|
|
|
|
mov ax,word ptr allocBreak
|
|
cmp ax,word ptr allocCount ; if allocBreak != allocCount
|
|
jnz cab_increment ; inc allocCount
|
|
mov ax,word ptr allocBreak+2
|
|
cmp ax,word ptr allocCount+2
|
|
jnz cab_increment
|
|
|
|
or ax,word ptr allocBreak ; if allocBreak is 0L, just inc.
|
|
jz cab_increment
|
|
|
|
krDebugOut <DEB_ERROR>, "Alloc break: Failing allocation"
|
|
|
|
stc ; return carry set
|
|
jmp short cab_exit
|
|
|
|
cab_increment:
|
|
inc word ptr allocCount ; increment allocCount
|
|
jnz cab_nofail
|
|
inc word ptr allocCount+2
|
|
cab_nofail:
|
|
clc
|
|
cab_exit:
|
|
assumes ds,NOTHING
|
|
cEnd
|
|
|
|
endif ;KDEBUG
|
|
|
|
sEnd CODE
|
|
|
|
sBegin NRESCODE
|
|
assumes CS,NRESCODE
|
|
assumes DS,NOTHING
|
|
assumes ES,NOTHING
|
|
|
|
externNP MapDStoDATA
|
|
externNP GetInstance
|
|
externNP StartProcAddress
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; CreateTask ;
|
|
; ;
|
|
; "Creates" a new task. It allocates the memory for the TDB+PDB struc, ;
|
|
; builds the PDB, constructs the TDB, initializes the EEMS memory ;
|
|
; arena, and sets the signature word in the TDB. TDB actually added ;
|
|
; to task queue by StartTask. ;
|
|
; ;
|
|
; Arguments: ;
|
|
; parmD pParmBlk ;
|
|
; parmW pExe ;
|
|
; parmW hPrev instance ;
|
|
; parmW fWOA ;
|
|
; ;
|
|
; Returns: ;
|
|
; AX = segment of TDB ;
|
|
; ;
|
|
; Error Returns: ;
|
|
; AX = 0 ;
|
|
; ;
|
|
; Registers Preserved: ;
|
|
; DI,SI,DS ;
|
|
; ;
|
|
; Registers Destroyed: ;
|
|
; ;
|
|
; Calls: ;
|
|
; ;
|
|
; History: ;
|
|
; ;
|
|
; Thu 04-Jan-1990 21:18:25 -by- David N. Weise [davidw] ;
|
|
; Added support for OS/2 apps. ;
|
|
; ;
|
|
; Mon 07-Aug-1989 23:28:15 -by- David N. Weise [davidw] ;
|
|
; Added support for long command lines to winoldap. ;
|
|
; ;
|
|
; Thu Apr 09, 1987 03:53:16p -by- David N. Weise [davidw] ;
|
|
; Added the initialization for EMS a while ago, recently added the ;
|
|
; switching of stacks to do it. ;
|
|
; ;
|
|
; Sun Feb 01, 1987 07:46:53p -by- David N. Weise [davidw] ;
|
|
; Added this nifty comment block. ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc CreateTask,<PUBLIC,FAR>,<si,di>
|
|
parmD pParmBlk
|
|
parmW pExe
|
|
; parmW fPrev
|
|
parmW fWOA
|
|
|
|
localW env_seg
|
|
localW comline_start
|
|
cBegin
|
|
call MapDStoDATA
|
|
ReSetKernelDS
|
|
cld
|
|
xor si,si
|
|
mov env_seg,si
|
|
mov comline_start,si
|
|
cmp si,pParmBlk.sel
|
|
jz parm_block_considered
|
|
cCall pass_environment,<pExe,pParmBlk>
|
|
inc ax
|
|
jnz @F
|
|
jmp ats6
|
|
@@: dec ax
|
|
mov env_seg,ax
|
|
mov comline_start,dx
|
|
mov si,size PDB ; start with size of PDB
|
|
cmp fWOA,0
|
|
jz parm_block_considered
|
|
les di,pParmBlk
|
|
les di,es:[di].lpcmdline
|
|
mov cx,es:[di]
|
|
sub cx,127 ; account for terminating 0Dh
|
|
jbe parm_block_considered
|
|
add si,cx
|
|
add si,15
|
|
and si,NOT 15
|
|
parm_block_considered:
|
|
add si,TDBsize+15 ; Room for task data and paragraph aligned.
|
|
; xor ax,ax ; Room for EMM save area if needed.
|
|
; mov al,fEMM
|
|
; add si,ax
|
|
and si,0FFF0h
|
|
mov di,si
|
|
mov cl,4
|
|
shr si,cl
|
|
ifdef WOW
|
|
; We need to ensure task handles are unique across multiple WOW VDMs
|
|
; on Windows NT, so that for example the undocumented feature of
|
|
; passing a 16-bit htask to Win32 Post(App|Thread)Message instead
|
|
; of a thread ID will work reliably with multiple WOW VDMs.
|
|
;
|
|
; To accomplish this we call WowReserveHtask, which will return
|
|
; the htask if the htask (ptdb) was previously unused and has
|
|
; been reserved for us. If it returns 0 another VDM is already
|
|
; using that value and so we need to allocate another and try again.
|
|
; To avoid risking exhausting low memory, we allocate memory for the
|
|
; TDB once using GlobalDOSAlloc, then clone it using AllocSelector.
|
|
; We test this cloned selector value using WowReserveHtask, if it
|
|
; fails we get another clone until one works. Then we free all but
|
|
; the clone we'll return, and magically swap things around so that
|
|
; the cloned selector owns the TDB memory and then free the original
|
|
; selector from GlobalDOSAlloc
|
|
;
|
|
|
|
xor dx,dx ; Make size of allocation a dword
|
|
regptr xsize,dx,di
|
|
cCall GlobalDOSAlloc,<xsize>
|
|
or ax,ax
|
|
jnz @f
|
|
jmp ats6 ; Return zero for failure.
|
|
|
|
@@: push di ; save TDB size on stack
|
|
push ax ; save GlobalDOSAlloc selector on stack
|
|
mov di,ax ; and in DI
|
|
cCall WowReserveHtask,<ax> ; returns htask or 0
|
|
or ax,ax ; Is this selector value avail as htask?
|
|
jz MustClone ; no, start cloning loop
|
|
pop ax ; htask to return
|
|
pop di ; TDB size
|
|
jmps NoClone
|
|
MustClone:
|
|
xor cx,cx ; count of clone selectors
|
|
xor si,si ; no selector to return yet
|
|
AnotherHtask:
|
|
push cx
|
|
cCall AllocSelector,<di> ; clone the selector
|
|
pop cx
|
|
or ax,ax
|
|
jz FreeAnyHtasks ; Out of selectors cleanup and exit
|
|
push ax ; save cloned selector on stack
|
|
inc cx
|
|
push cx
|
|
cCall WowReserveHtask,<ax> ; returns htask or 0
|
|
pop cx
|
|
or ax,ax
|
|
jz AnotherHtask ; conflict
|
|
mov si,ax ; SI = selector to return
|
|
pop bx ; pop the selector we're returning
|
|
dec cx
|
|
jcxz @f
|
|
FreeLoop:
|
|
pop bx ; pop an allocated selector from stack
|
|
push cx
|
|
cCall FreeSelector,<bx>
|
|
pop cx
|
|
dec cx
|
|
FreeAnyHtasks:
|
|
jcxz @f ; have we popped all the allocated selectors? Yes
|
|
jmps FreeLoop ; No
|
|
|
|
@@: mov ax,si
|
|
or si,si
|
|
jnz @f
|
|
pop ax ; original selector from GlobalDOSAlloc
|
|
cCall GlobalDOSFree,<ax>
|
|
pop di
|
|
jmp ats6
|
|
|
|
@@:
|
|
; SI is selector to return, top of stack is original GlobalDOSAlloc
|
|
; selector. We need to free the original selector and make the clone
|
|
; selector "own" the memory so it will be freed properly by GlobalDOSFree
|
|
; during task cleanup.
|
|
|
|
pop di ; DI = original GlobalDOSAlloc selector
|
|
push ds
|
|
mov ds, pGlobalHeap
|
|
UnSetKernelDS
|
|
.386
|
|
cCall far_get_arena_pointer32,<di>
|
|
push eax
|
|
cCall FarAssociateSelector32,<di,0,0>
|
|
pop eax
|
|
mov ds:[eax].pga_handle, si
|
|
cCall FarAssociateSelector32,<si,eax>
|
|
.286p
|
|
pop ds
|
|
ReSetKernelDS
|
|
cCall FreeSelector,<di>
|
|
mov ax,si ; AX is the final TDB selector/handle.
|
|
pop di ; TDB size
|
|
NoClone:
|
|
|
|
else
|
|
xor dx,dx ; Make size of allocation a dword
|
|
regptr xsize,dx,di
|
|
cCall GlobalDOSAlloc,<xsize>
|
|
or ax,ax
|
|
jnz @f
|
|
jmp ats6 ; Return zero for failure.
|
|
@@:
|
|
endif
|
|
mov es, ax
|
|
xor ax, ax ; zero allocated block
|
|
mov cx, di
|
|
shr cx, 1
|
|
xor di, di
|
|
rep stosw
|
|
|
|
mov ax, es
|
|
|
|
ats2a:
|
|
cCall FarSetOwner,<ax,ax> ; Set TDB owner to be itself
|
|
cmp fWOA,0 ; Is this WinOldApp?
|
|
mov ds,ax
|
|
UnSetKernelDS
|
|
jz no_it_isnt
|
|
or ds:[TDB_flags],TDBF_WINOLDAP
|
|
no_it_isnt:
|
|
|
|
; Initialize the task stack.
|
|
|
|
mov si,1 ; 1 for show means open window
|
|
les di,pParmBlk
|
|
mov ax,es
|
|
or ax,di
|
|
jnz @F
|
|
jmp ats4 ; AX = DI = 0 if no parmblock
|
|
|
|
@@: xor ax,ax ; Skip past EMM save area and
|
|
push ds
|
|
xor dx, dx
|
|
push es
|
|
mov es,pExe
|
|
mov dx,es:[ne_flags]
|
|
pop es
|
|
test dx,NEPROT
|
|
jz @F
|
|
or ds:[TDB_flags],TDBF_OS2APP
|
|
or ds:[TDB_ErrMode],08000h ; don't prompt for .DLL's
|
|
@@:
|
|
call MapDStoDATA
|
|
ReSetKernelDS
|
|
test dx,NEPROT ; OS/2 app?
|
|
mov dx,TopPDB ; DX has segment of parent PDB
|
|
jz use_kernel_TDB
|
|
; %OUT This should probably be Win_PDB
|
|
mov dx,cur_DOS_PDB ; inherit parent's stuff
|
|
use_kernel_TDB:
|
|
pop ds
|
|
UnSetKernelDS
|
|
|
|
push dx ; yes, get address of PDB
|
|
push es
|
|
mov si,(TDBsize+15) and not 15 ; Round up TDB size
|
|
|
|
cCall AllocSelector,<ds> ; Get us an alias selector
|
|
or ax, ax ; did we get it?
|
|
jnz ats_gotsel
|
|
mov bx, ds ; No, tidy up
|
|
mov ds, ax ; We will current ds, so zero it
|
|
cCall GlobalDOSFree,<bx> ; Free the memory
|
|
pop es
|
|
pop dx
|
|
xor ax, ax
|
|
jmp ats6
|
|
|
|
ats_gotsel:
|
|
xor dx, dx
|
|
cCall LongPtrAdd,<ax,dx,dx,si>
|
|
mov si, dx ; SI = selector of new PDB
|
|
pop es
|
|
pop dx
|
|
regptr esbx,es,bx ; es:bx points at parm block
|
|
mov bx,di
|
|
mov cx,256 ; just include enough room for PDB
|
|
cCall BuildPDB,<dx,si,esbx,cx,fWOA>; go build it
|
|
mov ax,si ; link on another PDB
|
|
push ds
|
|
call MapDStoDATA
|
|
ReSetKernelDS
|
|
xchg HeadPDB,ax
|
|
mov es,si
|
|
mov es:[PDB_Chain],ax
|
|
|
|
les di,pParmBlk
|
|
push si
|
|
lds si,es:[di].lpfcb1
|
|
UnSetKernelDS
|
|
mov di,PDB_5C_FCB
|
|
pop es
|
|
mov cx,ds
|
|
or cx,si
|
|
jz ats3b
|
|
mov cx,ds:[si]
|
|
inc cx
|
|
inc cx
|
|
cmp cx,24h
|
|
jbe ats3a
|
|
mov cx,24h
|
|
ats3a: rep movsb
|
|
ats3b: mov si,es
|
|
pop ds
|
|
|
|
mov ax,env_seg
|
|
or ax,ax
|
|
jz no_new_env
|
|
mov es:[PDB_environ],ax
|
|
no_new_env:
|
|
|
|
ats4: mov es,pExe
|
|
mov ds:[TDB_pModule],es ; Do this before InitTaskEMS
|
|
|
|
mov ax,comline_start ;!!! just for now os2
|
|
mov ds:[TDB_Validity],ax
|
|
|
|
push si
|
|
push ds
|
|
push ds
|
|
push es
|
|
pop ds
|
|
pop es
|
|
|
|
mov di,TDB_ModName
|
|
mov si,ds:[ne_restab]
|
|
lodsb ; get no of bytes in name
|
|
cbw
|
|
cmp ax,8
|
|
jbe @F
|
|
mov ax, ds
|
|
krDebugOut <DEB_WARN or DEB_krLoadMod>, "Module Name %AX0 (%AX1) too long"
|
|
mov ax,8
|
|
@@: mov cx,ax
|
|
cld
|
|
rep movsb
|
|
|
|
ifdef WOW
|
|
; (see other bug #74369 note)
|
|
; Load the App compatibility flags
|
|
; This ifdef WOW chunk is the same place as Win'95 task.asm to help get compat
|
|
; flags loaded sooner
|
|
mov cx,ds:[ne_expver]
|
|
mov es:[TDB_ExpWinVer],cx
|
|
|
|
cCall SetAppCompatFlags, <es>
|
|
mov es:[TDB_CompatFlags], ax
|
|
mov es:[TDB_CompatFlags2], dx
|
|
if KDEBUG
|
|
mov bx, ax
|
|
or bx, dx
|
|
jz @F
|
|
krDebugOut DEB_WARN, "Backward compatibility hack enabled: #dx#AX"
|
|
@@:
|
|
endif
|
|
endif
|
|
|
|
; initialize the interrupt vectors
|
|
|
|
mov di,TDB_INTVECS
|
|
call MapDStoDATA
|
|
ReSetKernelDS
|
|
ife ROM
|
|
mov ds,MyCSAlias
|
|
assumes ds,CODE
|
|
mov si,codeOffset prevInt00proc
|
|
else
|
|
mov si,dataOffset prevInt00proc
|
|
endif
|
|
mov cx,(4 * numTaskInts)/2
|
|
rep movsw
|
|
assumes ds,nothing
|
|
pop ds
|
|
pop si
|
|
|
|
cCall FarCreateTask ;,<fPrev>
|
|
jnc @F
|
|
jmp ats6
|
|
@@:
|
|
push ds
|
|
call MapDStoDATA
|
|
ReSetKernelDS
|
|
mov es,curTDB ; inherit the parents
|
|
pop ds
|
|
UnSetKernelDS
|
|
|
|
mov ds:[TDB_PDB],si ; save new PDB
|
|
or si,si ; do we have a new PDB?
|
|
jnz @F ; zero means no
|
|
mov si,es:[TDB_PDB]
|
|
mov ds:[TDB_PDB],si
|
|
@@: mov ds:[TDB_Parent],es
|
|
;
|
|
; Inherit parent's wow compatibiltiy flags
|
|
; Special code is required in wkman.c to exploit this
|
|
mov ax,es:[TDB_WOWCompatFlags]
|
|
mov ds:[TDB_WOWCompatFlags],ax
|
|
mov ax,es:[TDB_WOWCompatFlags2]
|
|
mov ds:[TDB_WOWCompatFlags2],ax
|
|
mov ax,es:[TDB_WOWCompatFlagsEx]
|
|
mov ds:[TDB_WOWCompatFlagsEx],ax
|
|
mov ax,es:[TDB_WOWCompatFlagsEx2]
|
|
mov ds:[TDB_WOWCompatFlagsEx2],ax
|
|
|
|
mov ds:[TDB_thread_tdb],ds
|
|
mov ds:[TDB_DTA].off,80h ; set initial DTA
|
|
mov ds:[TDB_DTA].sel,si
|
|
mov ds:[TDB_sig],TDB_SIGNATURE ; Set signature word.
|
|
|
|
mov ax,SEG default_sig_handler
|
|
mov ds:[TDB_ASignalProc].sel,ax
|
|
mov ax,codeOffset default_sig_handler
|
|
mov ds:[TDB_ASignalProc].off,ax
|
|
|
|
; Initialize the MakeProcInstance Thunks.
|
|
|
|
cCall AllocDStoCSAlias,<ds>
|
|
mov ds:[TDB_MPI_Sel],ax
|
|
mov ds:[TDB_MPI_Thunks],0
|
|
mov ds:[TDB_MPI_Thunks].2,MPIT_SIGNATURE
|
|
mov bx,TDB_MPI_Thunks + THUNKSIZE-2
|
|
mov cx,THUNKELEM-1
|
|
mov dx,bx
|
|
mp1: add dx,THUNKSIZE
|
|
.errnz THUNKELEM and 0FF00h
|
|
mov ds:[bx],dx
|
|
mov bx,dx
|
|
loop mp1
|
|
mov ds:[bx],cx
|
|
|
|
mov si, ds
|
|
mov di, ax
|
|
call MapDStoDATA
|
|
ReSetKernelDS
|
|
mov ds, pGlobalHeap
|
|
UnSetKernelDS
|
|
if PMODE32
|
|
.386
|
|
cCall far_get_arena_pointer32,<si>
|
|
cCall FarAssociateSelector32,<di, eax>
|
|
.286p
|
|
else
|
|
cCall far_get_arena_pointer,<si>
|
|
cCall FarAssociateSelector,<di, ax>
|
|
endif
|
|
mov ax, si
|
|
mov ds, si
|
|
ats6:
|
|
cEnd
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; pass_environment
|
|
;
|
|
;
|
|
; Entry:
|
|
;
|
|
; Returns:
|
|
; AX = seg of new env if any
|
|
; DX = start of comline
|
|
;
|
|
; Error Return:
|
|
; AX = -1
|
|
;
|
|
; Registers Destroyed:
|
|
;
|
|
; History:
|
|
; Wed 27-Dec-1989 23:36:25 -by- David N. Weise [davidw]
|
|
; Wrote it!
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
ifdef WOW
|
|
cProc pass_environment,<PUBLIC,NEAR>,<di,si,ds>
|
|
parmW pExe
|
|
parmD pParmBlk
|
|
cBegin
|
|
ReSetKernelDS
|
|
test fBooting,1
|
|
jz @F
|
|
xor ax,ax
|
|
jmp pe_exit
|
|
@@:
|
|
cCall WowPassEnvironment,<cur_DOS_PDB, pParmBlk, pExe>
|
|
or ax,ax
|
|
jz pe_error_exit
|
|
cCall FarSetOwner,<ax,pExe> ; Make this new guy the owner
|
|
jmps pe_exit
|
|
|
|
pe_error_exit:
|
|
mov ax, -1
|
|
pe_exit:
|
|
cEnd
|
|
|
|
else
|
|
|
|
cProc pass_environment,<PUBLIC,NEAR>,<di,si,ds>
|
|
|
|
parmW pExe
|
|
parmD pParmBlk
|
|
|
|
localW myEnv
|
|
cBegin
|
|
|
|
ReSetKernelDS
|
|
|
|
cld
|
|
test fBooting,1
|
|
jz @F
|
|
xor ax,ax
|
|
jmp pe_exit
|
|
@@:
|
|
|
|
cCall WowPassEnvironment,<Win_PDB, cur_DOS_PDB, pParmBlk, pExe>
|
|
|
|
mov es,curTDB
|
|
mov bl,es:[TDB_flags]
|
|
|
|
@@:
|
|
|
|
|
|
; massage environment
|
|
|
|
les di,pParmBlk
|
|
mov ax,es:[di].envseg
|
|
or ax,ax
|
|
jnz pe_given_env
|
|
; %OUT This should probably be Win_PDB
|
|
mov ds,cur_DOS_PDB
|
|
UnsetKernelDS
|
|
mov ax,ds:[PDB_environ]
|
|
|
|
pe_given_env:
|
|
mov myEnv,ax
|
|
mov es,ax ; ES => environment
|
|
xor ax,ax
|
|
mov cx,-1
|
|
xor di,di
|
|
@@: repnz scasb
|
|
cmp es:[di],al
|
|
jnz @B
|
|
neg cx
|
|
; dec cx ; include space for extra 0
|
|
push cx ; length of environment
|
|
mov dx,cx
|
|
|
|
; MORE TEST CODE TO SEE IF IT FIXES THE PROBLEM.
|
|
mov es,pExe
|
|
test es:[ne_flags],NEPROT
|
|
jnz @f
|
|
|
|
mov cx,3 ; Save room for magic word and nul
|
|
add dx,cx
|
|
push 8000h ; No command line after the env.
|
|
|
|
jmps pe_got_com_len
|
|
|
|
@@:
|
|
les di,pParmBlk
|
|
test bl,TDBF_OS2APP ; execer an OS/2 app?
|
|
jz pe_execer_dos_app
|
|
les di,es:[di].lpCmdLine
|
|
mov cx,-1
|
|
repnz scasb
|
|
repnz scasb ; get both strings
|
|
neg cx
|
|
add dx,cx
|
|
dec cx ; length of command line
|
|
or ch,80h ; mark special
|
|
push cx
|
|
jmps pe_got_com_len
|
|
|
|
pe_execer_dos_app:
|
|
inc es:[di].lpCmdLine.off
|
|
les di,es:[di].lpCmdLine
|
|
xor cx,cx
|
|
mov cl,es:[di][-1] ; length of command line
|
|
add dx,cx
|
|
inc dx ; We add a '\0' when we move it anyway
|
|
push cx
|
|
|
|
pe_got_com_len:
|
|
mov es,pExe
|
|
mov di,es:[ne_pfileinfo]
|
|
lea di,[di].opfile
|
|
mov cx,-1
|
|
repnz scasb
|
|
neg cx
|
|
dec cx
|
|
push cx ; length of file name
|
|
shl cx,1 ; for program pointer and arg 1
|
|
add dx,cx
|
|
|
|
cCall GlobalAlloc,<ax,ax,dx>
|
|
or ax,ax
|
|
jz @f
|
|
push ax
|
|
cCall FarSetOwner,<ax,pExe> ; Make this new guy the owner
|
|
pop ax
|
|
@@:
|
|
mov es,ax
|
|
pop dx ; length of filename
|
|
pop bx ; length of command line
|
|
pop cx ; length of environment
|
|
or ax,ax
|
|
jz pe_error_exit
|
|
|
|
mov ds,myEnv
|
|
xor di,di
|
|
xor si,si
|
|
rep movsb
|
|
|
|
mov ds,pExe
|
|
|
|
; MORE TEST CODE TO SEE IF IT FIXED THE PROBLEM
|
|
|
|
test ds:[ne_flags],NEPROT
|
|
jnz @f
|
|
|
|
mov ax,1
|
|
stosw
|
|
|
|
@@:
|
|
mov si,ds:[ne_pfileinfo]
|
|
lea si,[si].opfile
|
|
mov cx,dx ; length of filename
|
|
rep movsb
|
|
mov ax,di ; save position of comline start
|
|
|
|
test bh,80h ; if OS/2 execer comline is correct
|
|
jnz @F
|
|
mov si,ds:[ne_pfileinfo]
|
|
lea si,[si].opfile
|
|
mov cx,dx ; length of filename
|
|
rep movsb
|
|
|
|
@@: and bh,NOT 80h
|
|
lds si,pParmBlk
|
|
lds si,ds:[si].lpCmdLine
|
|
mov cx,bx
|
|
rep movsb
|
|
mov byte ptr es:[di],0 ; zero terminate
|
|
mov dx,ax ; comline start
|
|
mov ax,es
|
|
jmps pe_exit
|
|
|
|
pe_error_exit:
|
|
mov ax,-1
|
|
|
|
pe_exit:
|
|
|
|
cEnd
|
|
|
|
endif
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; StartLibrary ;
|
|
; ;
|
|
; Initialize library registers. ;
|
|
; ;
|
|
; Arguments: ;
|
|
; parmW hExe ;
|
|
; parmD lpParms ;
|
|
; parmD startAddr ;
|
|
; ;
|
|
; Returns: ;
|
|
; ;
|
|
; Error Returns: ;
|
|
; AX = 0 ;
|
|
; DS = data segment ;
|
|
; ;
|
|
; Registers Preserved: ;
|
|
; DI,SI ;
|
|
; ;
|
|
; Registers Destroyed: ;
|
|
; BX,CX,DX,ES ;
|
|
; ;
|
|
; Calls: ;
|
|
; GetInstance ;
|
|
; FarMyLock ;
|
|
; ;
|
|
; History: ;
|
|
; ;
|
|
; Thu 04-Jan-1990 22:48:25 -by- David N. Weise [davidw] ;
|
|
; Added support for OS/2 apps. ;
|
|
; ;
|
|
; Sat Apr 18, 1987 08:54:50p -by- David N. Weise [davidw] ;
|
|
; Added this nifty comment block. ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc StartLibrary,<PUBLIC,NEAR>,<ds,si,di>
|
|
parmW hExe
|
|
parmD lpParms
|
|
parmD startAddr
|
|
localW hStartSeg
|
|
cBegin
|
|
cCall MapDStoDATA
|
|
ReSetKernelDS
|
|
cmp loadTDB,0
|
|
je notloading
|
|
test kernel_flags,KF_pUID ; All done booting?
|
|
jz notloading
|
|
mov es,loadTDB
|
|
test es:[TDB_Flags],TDBF_OS2APP
|
|
jnz notloading
|
|
mov ax,hExe
|
|
mov es,es:[TDB_LibInitSeg]
|
|
mov bx,es:[pStackTop]
|
|
xchg es:[bx-2],ax
|
|
mov es:[bx],ax
|
|
add es:[pStackTop],2
|
|
mov ax,hExe
|
|
jmp slxx
|
|
|
|
notloading:
|
|
mov si,hExe
|
|
mov es,si
|
|
test es:[ne_flags],NEPROT
|
|
jnz no_user_yet
|
|
cmp pSignalProc.sel,0
|
|
jz no_user_yet
|
|
xor ax,ax
|
|
mov bx,40h
|
|
cCall pSignalProc,<hExe,bx,ax,ax,ax> ; SignalProc(hModule,40h,wParam,lParam)
|
|
no_user_yet:
|
|
cCall GetInstance,<si>
|
|
mov di,ax
|
|
if ROM
|
|
cCall FarIsROMObject, <SEG_startAddr>
|
|
or ax, ax
|
|
jz not_rom_code_segment
|
|
mov hStartSeg, 0
|
|
jmp sl_got_handle
|
|
not_rom_code_segment:
|
|
endif
|
|
cCall IGlobalHandle,<SEG_startAddr>
|
|
xchg startAddr.sel,dx
|
|
mov hStartSeg,ax
|
|
|
|
if ROM
|
|
sl_got_handle:
|
|
endif
|
|
|
|
;** Send the SDM_LOADDLL notification
|
|
mov bx,startAddr.off
|
|
mov cx,startAddr.sel
|
|
mov ax,SDM_LOADDLL
|
|
cCall MyFarDebugCall
|
|
|
|
cmp SEG_startAddr, 0
|
|
jnz HaveStart
|
|
mov ax, di
|
|
jmps slxx
|
|
HaveStart:
|
|
cCall IGlobalHandle,<di>
|
|
mov ds,si
|
|
UnSetKernelDS
|
|
mov cx,ds:[ne_heap]
|
|
mov ds,dx
|
|
les si,lpParms
|
|
mov ax,es
|
|
or ax,ax
|
|
jz dont_fault
|
|
les si,es:[si].lpcmdline
|
|
dont_fault:
|
|
mov ax,1 ; An Arts & Letters lib init doesn't
|
|
push di ; touch AX!!
|
|
ifdef WOW
|
|
push cs
|
|
push offset RetAddr
|
|
pushf
|
|
push startAddr.sel
|
|
push startAddr.off
|
|
|
|
push ax
|
|
|
|
push ds
|
|
|
|
push ax
|
|
mov ax,hExe
|
|
mov ds,ax
|
|
pop ax
|
|
|
|
push 0 ; hTask (meaningless for a DLL)
|
|
|
|
push ds ; hModule
|
|
|
|
push ds ; Pointer to module name
|
|
push ds:ne_restab
|
|
push ds ; Pointer to module path
|
|
push word ptr ds:ne_crc+2
|
|
|
|
cCall MapDStoDATA
|
|
ReSetKernelDS ds
|
|
push DBG_DLLSTART
|
|
|
|
test DebugWOW,DW_DEBUG
|
|
jz skip_bop
|
|
|
|
FBOP BOP_DEBUGGER,,FastBop
|
|
.286p
|
|
|
|
skip_bop:
|
|
add sp,+14
|
|
|
|
pop ds
|
|
UnSetKernelDS ds
|
|
pop ax
|
|
iret
|
|
|
|
RetAddr equ $
|
|
|
|
else
|
|
cCall SafeCall,<startAddr>
|
|
endif
|
|
pop di ; USER.EXE didn't save DI, maybe others
|
|
or ax,ax
|
|
jz slx
|
|
mov ax,di
|
|
slx:
|
|
push ax
|
|
if ROM
|
|
cmp hStartSeg, 0
|
|
jz @F
|
|
cCall GlobalLRUOldest,<hStartSeg>
|
|
@@:
|
|
endif
|
|
pop ax
|
|
slxx:
|
|
cEnd
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; StartTask ;
|
|
; ;
|
|
; Sets up the standard register values for a Windows task. ;
|
|
; ;
|
|
; Arguments: ;
|
|
; HANDLE hPrev = a previous instance ;
|
|
; HANDLE hExe = the EXE header ;
|
|
; FARP stackAddr = the normal task stack address (initial SS:SP) ;
|
|
; FARP startAddr = the normal task start address (initial CS:IP) ;
|
|
; ;
|
|
; Returns: ;
|
|
; AX = HANDLE ;
|
|
; ;
|
|
; Error Returns: ;
|
|
; AX = NULL ;
|
|
; ;
|
|
; Registers Preserved: ;
|
|
; ;
|
|
; Registers Destroyed: ;
|
|
; ;
|
|
; Calls: ;
|
|
; GetInstance ;
|
|
; FarMyLock ;
|
|
; ;
|
|
; History: ;
|
|
; ;
|
|
; Tue Apr 21, 1987 06:41:05p -by- David N. Weise [davidw] ;
|
|
; Added the EMS initialization of the entry tables in page 0. ;
|
|
; ;
|
|
; Thu Dec 11, 1986 11:38:53a -by- David N. Weise [dnw] ;
|
|
; Removed the superfluous call to calculate the largesr NR seg. ;
|
|
; ;
|
|
; Fri Sep 19, 1986 12:08:23p -by- Charles Whitmer [cxw] ;
|
|
; Made it return 0000 on error rather than terminate. ;
|
|
; ;
|
|
; Thu Sep 18, 1986 02:33:39p -by- Charles Whitmer [cxw] ;
|
|
; Wrote it. ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc StartTask,<PUBLIC,NEAR>,<si,di>
|
|
parmW hPrev
|
|
parmW hExe
|
|
parmD stackAddr
|
|
parmD startAddr
|
|
cBegin
|
|
cCall MapDStoDATA
|
|
ReSetKernelDS
|
|
xor di,di
|
|
cmp loadTDB,di
|
|
jnz st1
|
|
jmp stx
|
|
|
|
stfail0:
|
|
xor ax,ax
|
|
pop ds
|
|
jmp stfail
|
|
|
|
st1: push ds
|
|
cmp stackAddr.sel,di
|
|
jz stfail0
|
|
|
|
cmp startAddr.sel,di
|
|
jz stfail0
|
|
|
|
mov ds,loadTDB
|
|
UnSetKernelDS
|
|
cmp ds:[TDB_sig],TDB_SIGNATURE
|
|
jnz stfail0
|
|
|
|
; Get new task stack
|
|
|
|
cCall IGlobalHandle,<SEG_stackAddr>
|
|
mov ds:[TDB_taskSS],dx
|
|
mov ax,stackAddr.off
|
|
sub ax,(SIZE TASK_REGS)
|
|
mov ds:[TDB_taskSP],ax
|
|
|
|
; get my instance
|
|
|
|
cCall GetInstance,<hExe>
|
|
mov di,ax
|
|
mov ds:[TDB_Module],ax
|
|
|
|
; find my real code segment
|
|
|
|
cCall IGlobalHandle,<SEG_startAddr>
|
|
or dx,dx
|
|
jz stfail0
|
|
mov startAddr.sel,dx
|
|
|
|
; find my real data segment
|
|
|
|
cCall IGlobalHandle,<di> ; DI = handle of DGROUP
|
|
mov si,dx ; SI = address of DGROUP
|
|
|
|
if KDEBUG
|
|
|
|
; Set up the allocBreak globals if needed
|
|
|
|
cCall SetupAllocBreak,<ds>
|
|
|
|
endif ;KDEBUG
|
|
|
|
; copy junk from hExe -> TDB
|
|
|
|
mov es,hExe
|
|
mov cx,es:[ne_expver]
|
|
mov ds:[TDB_ExpWinVer],cx
|
|
mov cx,es:[ne_stack] ; CX = STACKSIZE
|
|
mov dx,es:[ne_heap] ; DX = HEAPSIZE
|
|
|
|
|
|
|
|
; set up the task registers
|
|
|
|
test es:[ne_flags],NEPROT
|
|
jnz st_OS2_binary
|
|
|
|
les bx,dword ptr ds:[TDB_TaskSP]
|
|
mov es:[bx].TASK_AX,0 ; Task AX = NULL
|
|
mov ax,ds:[TDB_PDB]
|
|
mov es:[bx].TASK_ES,ax ; Task ES = PDB
|
|
mov es:[bx].TASK_DI,di ; Task DI = hInstance or hExe
|
|
mov es:[bx].TASK_DS,si ; Task DS = data segment
|
|
mov ax,hPrev
|
|
mov es:[bx].TASK_SI,ax ; Task SI = previous instance
|
|
mov es:[bx].TASK_BX,cx ; Task BX = STACKSIZE
|
|
mov es:[bx].TASK_CX,dx ; Task CX = HEAPSIZE
|
|
mov es:[bx].TASK_BP,1 ; Task BP = 1 (far frame)
|
|
jmps st_regs_set
|
|
|
|
st_OS2_binary:
|
|
push di
|
|
mov es,ds:[TDB_PDB]
|
|
mov di,es:[PDB_environ]
|
|
les bx,dword ptr ds:[TDB_TaskSP]
|
|
mov es:[bx].TASK_AX,di ; Task AX = environment
|
|
mov es:[bx].TASK_DX,cx ; Task DX = STACKSIZE
|
|
lsl cx,si
|
|
inc cx
|
|
mov es:[bx].TASK_CX,cx ; Task CX = Length of data segment
|
|
mov ax,ds:[TDB_pModule]
|
|
mov es:[bx].TASK_DI,ax ; Task DI = hExe
|
|
mov es:[bx].TASK_SI,dx ; Task SI = HEAPSIZE
|
|
mov es:[bx].TASK_DS,si ; Task DS = data segment
|
|
mov es:[bx].TASK_ES,0 ; Task ES = 0
|
|
mov es:[bx].TASK_BP,1 ; Task BP = 1 (far frame)
|
|
xor ax,ax
|
|
xchg ax,ds:[TDB_Validity]
|
|
mov es:[bx].TASK_BX,ax ; Task BX = offset in env of comline
|
|
pop di
|
|
|
|
st_regs_set:
|
|
|
|
pop ds
|
|
push ds
|
|
ReSetKernelDS
|
|
|
|
test Kernel_Flags[2],KF2_PTRACE ;TOOLHELP.DLL and/or WINDEBUG.DLL?
|
|
jz st_NoPTrace
|
|
|
|
mov ax,startAddr.sel
|
|
mov ptrace_app_entry.sel,ax
|
|
mov ax,startAddr.off
|
|
mov ptrace_app_entry.off,ax
|
|
|
|
mov ax,SEG CVW_HACK
|
|
mov ds,ax
|
|
UnSetKernelDS
|
|
mov ax,codeOffset CVW_Hack
|
|
jmps st_PTraceHere
|
|
|
|
st_NoPTrace:
|
|
lds ax,startAddr ; Task CS:IP = start address
|
|
UnSetKernelDS
|
|
st_PTraceHere:
|
|
mov es:[bx].TASK_CS,ds
|
|
mov es:[bx].TASK_IP,ax
|
|
pop ds
|
|
ReSetKernelDS
|
|
|
|
stx: mov ax,di
|
|
stfail:
|
|
cEnd
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; InitTask ;
|
|
; ;
|
|
; This should be the first thing called by app when first started. ;
|
|
; It massages the registers, massages the command line and inits ;
|
|
; the heap. ;
|
|
; ;
|
|
; Arguments: ;
|
|
; ;
|
|
; When a windows application starts up the registers look ;
|
|
; like this: ;
|
|
; ;
|
|
; AX = 0 ;
|
|
; BX = stack size ;
|
|
; CX = heap size ;
|
|
; DX = ? ;
|
|
; DI = hInstance ;
|
|
; SI = hPrevInstance ;
|
|
; BP = 0 ;
|
|
; ES = Segment of Program Segment Prefix (see page E-8) ;
|
|
; DS = Applications DS ;
|
|
; SS = DS ;
|
|
; SP = stack area ;
|
|
; ;
|
|
; FCB1 field at PSP:5CH contains up to 24h bytes of binary data. ;
|
|
; Windows apps get their ShowWindow parameter in the first word of ;
|
|
; of this data. ;
|
|
; ;
|
|
; Returns: ;
|
|
; AX = PSP address ;
|
|
; CX = stack limit ;
|
|
; DX = command show ;
|
|
; ES:BX = command line ;
|
|
; ;
|
|
; Error Returns: ;
|
|
; ;
|
|
; Registers Preserved: ;
|
|
; ;
|
|
; Registers Destroyed: ;
|
|
; ;
|
|
; Calls: ;
|
|
; LocalInit ;
|
|
; FarEMS_FirstTime ;
|
|
; ;
|
|
; History: ;
|
|
; ;
|
|
; Mon 11-Sep-1989 19:13:52 -by- David N. Weise [davidw] ;
|
|
; Remove entry of AX = validity check. ;
|
|
; ;
|
|
; Wed Mar 16, 1988 22:45:00a -by- T.H. [ ] ;
|
|
; Fix bug in exit path. It was not popping the saved DS from the ;
|
|
; far call frame properly. Normally, this is not a problem (since ;
|
|
; it does indeed save the DS register across the entire routine), ;
|
|
; but if the RET has to go through a RetThunk, the saved DS is not ;
|
|
; really the original DS value, but a special value needed by the ;
|
|
; INT3F RetThunk code. This causes a crash when something in this ;
|
|
; routine (like the call to UserInitDone) causes our calling code ;
|
|
; segment to be discarded. ;
|
|
; ;
|
|
; Sat Apr 18, 1987 08:43:54p -by- David N. Weise [davidw] ;
|
|
; Added this nifty comment block. ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
STACKSLOP equ 150 ; stack slop for interrupt overhead
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
; ES = TDB
|
|
|
|
public do_libinit
|
|
do_libinit proc near
|
|
push si
|
|
push es
|
|
mov si,es:[TDB_LibInitOff]
|
|
mov es,cx
|
|
libinit_loop:
|
|
cld
|
|
lods word ptr es:[si]
|
|
or ax,ax
|
|
jz libinit_done
|
|
push es
|
|
mov es,ax
|
|
cmp es:[ne_magic],NEMAGIC
|
|
jne libinit_loop1
|
|
mov ax,-1
|
|
push es
|
|
cCall StartProcAddress,<es,ax>
|
|
pop es
|
|
;;; jcxz libinit_loop1
|
|
xor cx,cx
|
|
cCall StartLibrary,<es,cx,cx,dx,ax>
|
|
or ax,ax
|
|
jnz libinit_loop1
|
|
mov ax,4CF0h
|
|
DOSFCALL
|
|
libinit_loop1:
|
|
pop es
|
|
jmp libinit_loop
|
|
libinit_done:
|
|
|
|
mov si,es
|
|
cCall GlobalUnlock,<si>
|
|
cCall GlobalFree,<si>
|
|
pop es
|
|
mov es:[TDB_LibInitSeg],0
|
|
mov es:[TDB_LibInitOff],0
|
|
pop si
|
|
ret
|
|
do_libinit endp
|
|
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc InitTask,<PUBLIC,FAR>
|
|
cBegin nogen
|
|
pop ax ; Get return address
|
|
pop dx
|
|
mov ss:[pStackMin],sp ; Save bottom of stack
|
|
mov ss:[pStackBot],sp
|
|
sub bx,sp ; Compute top of stack
|
|
neg bx
|
|
add bx,STACKSLOP
|
|
mov ss:[pStackTop],bx ; Setup for chkstk
|
|
|
|
xor bp,bp ; Initial stack frame
|
|
push bp ; is not a far frame as there
|
|
mov bp,sp ; is no return address
|
|
push dx ; Push return address back on
|
|
push ax
|
|
inc bp
|
|
push bp
|
|
mov bp,sp
|
|
push ds
|
|
jcxz noheap ; Initialize local heap if any
|
|
xor ax,ax
|
|
push es
|
|
cCall LocalInit,<ax,ax,cx>
|
|
pop es
|
|
or ax,ax
|
|
jnz noheap
|
|
push ds
|
|
jmp noinit
|
|
noheap:
|
|
push es
|
|
cCall GetCurrentTask
|
|
mov es,ax
|
|
mov cx,es:[TDB_LibInitSeg]
|
|
jcxz no_libinit
|
|
call do_libinit
|
|
no_libinit:
|
|
ifdef WOW
|
|
; (see other bug #74369 note)
|
|
; App compatibility flags are set during CreateTask time to make them avilable
|
|
; to .dll's that are loaded by do_libinit (this is the same as Win'95)
|
|
else
|
|
call SetAppCompatFlags
|
|
mov es:[TDB_CompatFlags], ax
|
|
mov es:[TDB_CompatFlags2], dx
|
|
if KDEBUG
|
|
mov bx, ax
|
|
or bx, dx
|
|
jz @F
|
|
krDebugOut DEB_WARN, "Backward compatibility hack enabled: #dx#AX"
|
|
@@:
|
|
endif
|
|
endif
|
|
|
|
pop es
|
|
|
|
push ds
|
|
cCall MapDStoDATA
|
|
ReSetKernelDS
|
|
test kernel_flags,KF_pUID ; All done booting?
|
|
jnz noboot ; Yes, continue
|
|
or kernel_flags,KF_pUID
|
|
mov fBooting,0
|
|
mov cx,ds
|
|
|
|
pop ds ; DS = caller's data segment
|
|
UnSetKernelDS
|
|
push es ; Save ES
|
|
push ax
|
|
push cx
|
|
cCall IGlobalHandle,<ds>
|
|
push ax
|
|
cCall UnlockSegment,<ds>
|
|
xor dx,dx
|
|
cCall GlobalCompact,<dx,dx> ; Compact memory
|
|
xor dx,dx
|
|
cCall GlobalCompact,<dx,dx> ; Once more for completeness
|
|
cCall IGlobalHandle ; ,<ax> from above
|
|
mov ds,dx
|
|
cCall LockSegment,<ds>
|
|
|
|
pop cx
|
|
push ds
|
|
mov ds,cx
|
|
ReSetKernelDS
|
|
cmp pUserInitDone.sel,0 ; for Iris's server
|
|
jz no_User_to_call
|
|
call pUserInitDone ; Let USER lock down stuff.
|
|
no_USER_to_call:
|
|
pop ds
|
|
UnSetKernelDS
|
|
pop ax
|
|
pop es
|
|
push ds
|
|
|
|
IF PMODE32
|
|
;** Initialize the reboot stuff here
|
|
push es ; Save across call
|
|
cCall KRebootInit ; Local reboot init code
|
|
pop es
|
|
ENDIF
|
|
|
|
|
|
noboot:
|
|
mov bx,PDB_DEF_DTA ; point at command line
|
|
mov cx,bx ; save copy in cx
|
|
cmp bh,es:[bx] ; any chars in command line?
|
|
je ws3a ; no - exit
|
|
ws1: inc bx ; point to next char
|
|
mov al,es:[bx] ; get the char
|
|
cmp al,' ' ; SPACE?
|
|
je ws1
|
|
cmp al,9 ; TAB?
|
|
je ws1
|
|
mov cx,bx ; save pointer to beginning
|
|
dec bx ; compensate for next inc
|
|
ws2: inc bl ; move to next char
|
|
jz ws3a ; bailout if wrapped past 0FFh
|
|
cmp byte ptr es:[bx],13 ; end of line?
|
|
jne ws2
|
|
ws3:
|
|
mov byte ptr es:[bx],0 ; null terminate the line
|
|
ws3a:
|
|
mov bx,cx ; ES:BX = command line
|
|
mov cx,ss:[pStackTop] ; CX = stack limit
|
|
mov dx,1 ; DX = default cmdshow
|
|
cmp word ptr es:[PDB_5C_FCB],2 ; Valid byte count?
|
|
jne wsa4 ; No, use default
|
|
mov dx,word ptr es:[PDB_5C_FCB][2] ; Yes, DX = passed cmdshow
|
|
wsa4:
|
|
mov ax,es ; AX = PSP address
|
|
noinit:
|
|
pop ds
|
|
|
|
; THIS is correct way to pop the call frame. Must pop the saved
|
|
; DS properly from stack (might have been plugged with a RetThunk).
|
|
|
|
sub bp,2
|
|
mov sp,bp
|
|
pop ds
|
|
pop bp
|
|
dec bp
|
|
ret
|
|
cEnd nogen
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; InitLib ;
|
|
; ;
|
|
; Does what it says. ;
|
|
; ;
|
|
; Arguments: ;
|
|
; CX = # bytes wanted for heap ;
|
|
; ;
|
|
; Returns: ;
|
|
; ES:SI => null command line ;
|
|
; ;
|
|
; Error Returns: ;
|
|
; CX = 0 ;
|
|
; ;
|
|
; Registers Preserved: ;
|
|
; DI,DS ;
|
|
; ;
|
|
; Registers Destroyed: ;
|
|
; AX,BX,DX ;
|
|
; ;
|
|
; Calls: ;
|
|
; LocalInit ;
|
|
; ;
|
|
; History: ;
|
|
; ;
|
|
; Sat Apr 18, 1987 08:31:27p -by- David N. Weise [davidw] ;
|
|
; Added this nifty comment block. ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc InitLib,<PUBLIC,FAR>
|
|
cBegin nogen
|
|
xor ax,ax
|
|
jcxz noheap1 ; Done if no heap
|
|
mov si,cx
|
|
cCall LocalInit,<ax,ax,cx>
|
|
jcxz noheap1 ; Done if no heap
|
|
mov cx,si
|
|
noheap1:
|
|
push ds
|
|
cCall MapDStoDATA
|
|
push ds
|
|
pop es
|
|
pop ds
|
|
mov si,codeOFFSET nullcomline
|
|
ret
|
|
cEnd nogen
|
|
|
|
if KDEBUG
|
|
|
|
if 0
|
|
;-----------------------------------------------------------------------
|
|
; SetupAllocBreak
|
|
;
|
|
; Initializes the allocation break globals
|
|
; from the ALLOCBRK environment variable.
|
|
;
|
|
; ALLOCBRK=MODULE,0x12345678
|
|
;
|
|
; Assumes:
|
|
; DS = loadTDB
|
|
;
|
|
; Trashes:
|
|
; ES, SI, AX, BX, CX, DX
|
|
;
|
|
szALLOCBRK db "ALLOCBRK="
|
|
cchALLOCBRK equ $-szALLOCBRK
|
|
|
|
cProc SetupAllocBreak,<NEAR, PUBLIC>,<SI>
|
|
cBegin
|
|
mov es,ds:[TDB_PDB]
|
|
mov es,es:[PDB_environ]
|
|
|
|
lea bx,szALLOCBRK
|
|
mov dx,cchALLOCBRK
|
|
call LookupEnvString
|
|
or bx,bx
|
|
jz nomatch
|
|
;
|
|
; See if TDB_ModName is the same as the ALLOCBRK= module.
|
|
;
|
|
mov si,TDB_ModName
|
|
modloop:
|
|
mov al,es:[bx] ; get next environment char
|
|
or al,al
|
|
jz nomatch ; if at end of environment, no match
|
|
cmp al,','
|
|
jz match ; if at comma, then they might match
|
|
cmp al,ds:[si]
|
|
jnz nomatch
|
|
inc bx ; advance ptrs and try next char
|
|
inc si
|
|
jmp modloop
|
|
match:
|
|
cmp byte ptr ds:[si],0 ; at end of module name string?
|
|
jnz nomatch
|
|
|
|
inc bx ; skip past comma.
|
|
call ParseHex ; parse hex constant into dx:ax
|
|
|
|
SetKernelDSNRes es
|
|
mov word ptr es:allocBreak,ax
|
|
mov word ptr es:allocBreak+2,dx
|
|
|
|
or ax,dx ; if allocBreak is 0, clear allocTask
|
|
jz @F
|
|
mov ax,ds ; otherwise allocTask = loadTDB.
|
|
@@:
|
|
mov es:allocTask,ax
|
|
|
|
xor ax,ax ; reset allocCount
|
|
mov word ptr es:allocCount,ax
|
|
mov word ptr es:allocCount+2,ax
|
|
nomatch:
|
|
cEnd
|
|
|
|
;-----------------------------------------------------------------------
|
|
; LookupEnvString
|
|
;
|
|
; ES -> environment segment
|
|
; CS:BX -> string to search for (which must include trailing '=')
|
|
; DX -> length of string to search for
|
|
;
|
|
; returns:
|
|
; es:bx = pointer to environment string past '='
|
|
;
|
|
cProc LookupEnvString,<NEAR, PUBLIC>,<SI,DI,DS>
|
|
cBegin
|
|
push cs ; ds = cs
|
|
pop ds
|
|
|
|
cld
|
|
xor di,di ;start at beginning of environment seg
|
|
lenv_nextstring:
|
|
mov si,bx ;si = start of compare string
|
|
mov cx,dx ;cx = string length
|
|
mov ax,di ;Save current position in env seg
|
|
repe cmpsb
|
|
je lenv_foundit
|
|
|
|
mov di,ax ; start at beginning again
|
|
xor ax,ax ; and skip to end.
|
|
xor cx,cx
|
|
dec cx ; cx = -1
|
|
repne scasb
|
|
cmp es:[di],al ;End of environment?
|
|
jne lenv_nextstring ;No, try next string
|
|
xor bx,bx ; BX == NULL == not found.
|
|
jmp short lenv_exit
|
|
|
|
lenv_foundit:
|
|
mov bx,di
|
|
lenv_exit:
|
|
cEnd
|
|
|
|
;---------------------------------------------------------------------------
|
|
;
|
|
; ParseHex
|
|
;
|
|
; Assumes:
|
|
; es:bx - pointer to hex string of form 0x12345678
|
|
;
|
|
; Returns:
|
|
; Hex value in dx:ax, es:bx pointing to char past constant.
|
|
;
|
|
; Trashes:
|
|
; cx
|
|
;
|
|
cProc ParseHex,<NEAR, PUBLIC>
|
|
cBegin
|
|
xor dx,dx ; zero break count
|
|
xor ax,ax
|
|
xor cx,cx ; clear hi byte of char
|
|
hexloop:
|
|
mov cl,es:[bx] ; get first digit
|
|
jcxz parse_exit
|
|
inc bx
|
|
cmp cl,' ' ; skip spaces
|
|
jz hexloop
|
|
cmp cl,'x' ; skip 'x' or 'X'
|
|
jz hexloop
|
|
cmp cl,'X'
|
|
jz hexloop
|
|
|
|
cmp cl,'0' ; '0'..'9'?
|
|
jb parse_exit
|
|
cmp cl,'9'
|
|
jbe hexdigit
|
|
|
|
or cl,'a'-'A' ; convert to lower case
|
|
|
|
cmp cl,'a' ; 'a'..'f'?
|
|
jb parse_exit
|
|
cmp cl,'f'
|
|
ja parse_exit
|
|
|
|
sub cl,'a'-'0'-10
|
|
hexdigit:
|
|
sub cl,'0'
|
|
|
|
add ax,ax ; dx:ax *= 16
|
|
adc dx,dx
|
|
add ax,ax
|
|
adc dx,dx
|
|
add ax,ax
|
|
adc dx,dx
|
|
add ax,ax
|
|
adc dx,dx
|
|
|
|
add ax,cx ; add in the new digit
|
|
adc dx,0
|
|
|
|
jmp hexloop
|
|
parse_exit:
|
|
cEnd
|
|
endif; 0
|
|
|
|
endif ;KDEBUG
|
|
|
|
sEnd NRESCODE
|
|
|
|
|
|
if KDEBUG
|
|
|
|
sBegin CODE
|
|
assumes cs,CODE
|
|
;------------------------------------------------------------------------
|
|
;
|
|
; char FAR* GetTaskModNamePtr(HTASK htask)
|
|
;
|
|
; Returns a far pointer to a task's module name
|
|
; Used by SetupAllocBreak to access the task module name.
|
|
;
|
|
; Coded in assembly because no C header file that describes
|
|
; the TDB exists (and it's a little late to create one now)
|
|
;
|
|
cProc GetTaskModNamePtr,<NEAR, PUBLIC>
|
|
ParmW htask
|
|
cBegin
|
|
mov dx,htask
|
|
mov ax,TDB_ModName
|
|
cEnd
|
|
|
|
sEnd CODE
|
|
endif; KDEBUG
|
|
|
|
|
|
sBegin MISCCODE
|
|
assumes cs, misccode
|
|
assumes ds, nothing
|
|
assumes es, nothing
|
|
|
|
externNP MISCMapDStoDATA
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; GetDOSEnvironment
|
|
;
|
|
; Gets a pointer to the current task's starting environment string.
|
|
; Basically used by DLL's to find the environment.
|
|
;
|
|
; Entry:
|
|
; none
|
|
;
|
|
; Returns:
|
|
; DX:AX = pointer to current task's starting environment string
|
|
;
|
|
; Registers Destroyed:
|
|
;
|
|
; History:
|
|
; Tue 13-Jun-1989 20:52:58 -by- David N. Weise [davidw]
|
|
; Wrote it!
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc GetDOSEnvironment,<PUBLIC,FAR>
|
|
cBegin nogen
|
|
|
|
push ds
|
|
call GetCurrentTask
|
|
mov ds,ax
|
|
mov ds,ds:[TDB_PDB]
|
|
mov dx,ds:[PDB_environ]
|
|
xor ax,ax
|
|
pop ds
|
|
ret
|
|
|
|
cEnd nogen
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; GetNumTasks ;
|
|
; ;
|
|
; Gets the number of tasks (AKA TDB) in the system. ;
|
|
; ;
|
|
; Arguments: ;
|
|
; none ;
|
|
; ;
|
|
; Returns: ;
|
|
; AX = number of tasks ;
|
|
; ;
|
|
; Error Returns: ;
|
|
; ;
|
|
; Registers Preserved: ;
|
|
; all ;
|
|
; ;
|
|
; Registers Destroyed: ;
|
|
; ;
|
|
; Calls: ;
|
|
; nothing ;
|
|
; ;
|
|
; History: ;
|
|
; ;
|
|
; Thu Apr 09, 1987 11:34:30p -by- David N. Weise [davidw] ;
|
|
; Wrote it. ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc GetNumTasks,<PUBLIC,FAR>
|
|
cBegin nogen
|
|
xor ax,ax
|
|
push ds
|
|
call MISCMapDStoDATA
|
|
ReSetKernelDS
|
|
mov al,num_tasks
|
|
pop ds
|
|
UnSetKernelDS
|
|
ret
|
|
cEnd nogen
|
|
|
|
sEnd MISCCODE
|
|
|
|
end
|