;       SCCSID = @(#)tkscan.asm	6.1 90/11/17
SCCSID	equ	"@(#)tkscan.asm	13.25 90/07/10"

;	Tasking - ScanTasks subroutines
;
;	Created	  Feb 89	Jameel Hyder.
;
;	IBM/Microsoft Confidential
;
;	Copyright (c) IBM Corporation 1987, 1989
;	Copyright (c) Microsoft Corporation 1987, 1989
;
;	All Rights Reserved
;
INCL_ERROR_H	EQU	1		; for bseerr.inc

.xlist
include	fnotask.inc
include dosseg.inc
include basemaca.inc
include osmaca.inc
include oldmaca.inc
include osconst.inc
include dossymc.inc
include sigdef.inc
include except.inc
include infoseg.inc
include pgexport.inc
include vmexport.inc
include selxport.inc
include tkexport.inc
include curdir.inc
include dirent.inc
include find.inc
include screen.inc
include sem.inc
include tkptda.inc
include seldesc.inc
include kmode.inc
include mi.inc
include bseerr.inc
.list

	ModName tkscan,FNO_TKSCAN_ASM
	CpuMode 386

	EXTRN32 _TKScanTasks

;***LT	CallerRegs - Structure used by ScanTasks to save user registers.
;	These are used by the worker. Essentially an interface to old code.

CallerRegs	STRUC
C_BP	DW	?			; bp to pass to worker
C_DI	DW	?			; address of routine to call
C_CS	DW	?			; for far callers to scantaks
C_DS	DW	?
C_DX	DW	?
C_CX	DW	?
CallerRegs	ENDS


;***LT	StackFrame - Stack as it looks like at entry to the faronly version
;	of ScanTasks
StackFrame	STRUC
	DW	?		; saved BP
RetAddr DD	?		; far return address
StackFrame	ENDS


	FARCODE HIGH3
HIGH3CODE	SEGMENT

;***EP	ScanTasks - Near 16 callable interface to TKScanTasks.
;
;	The caller supplies the offset of a worker routine that is a near
;	routine	 relative to the caller's CS.  The worker is called once for
;	each task that belongs to the specified group, and is presented with a
;	pointer to the Per-Task Data Area (PTDA) of a task in the group on
;	each call in ES.  The scan can optionally be terminated if the worker
;	returns with the carry flag set.  In this case, the value left in AX
;	by the final call to the worker is also returned.
;
;	The supplied routine must NOT yield the CPU as processes belonging to
;	the set may be missed if there are changes in the process hierarchy
;	during the yield.
;
;	The order in which the processes are presented to the worker routine
;	is not defined, except that a parent process is always accessed before
;	any of its children.
;
;	ScanTasks will never reference a zombie process.
;
;	NOTE	The worker may use AX,BX,CX,DX,BP,DS.  Additionally, the values
;		set by the worker in BL,CX,DX and DS are preserved across
;		calls to the worker and the values returned in them by the
;		final worker call are returned. A worker can modify DI, if
;		it so chooses, as a means of changing the worker routine.
;
;	ENTRY	BL = Type of task group to be scanned
;
;		TK_TG_CSUB	- Scan all tasks in a command subtree
;		TK_TG_ONE	- Scan individual task
;		TK_TG_TREE	- Scan task and its descendants
;		TK_TG_SCRN	- Scan all tasks in a screen group
;		TK_TG_ALL	- Scan all tasks
;
;		BH = Scan flags
;
;		TK_SF_WORKER	- Stop the scan if the worker returns
;				      with the carry flag set.
;
;		CX = Id of task group to be scanned
;
;		   = Command subtree id if BL = TK_TG_CSUB
;		   = Process id		if BL = TK_TG_ONE
;		   = Process id of root if BL = TK_TG_TREE
;		   = Screen Group id	if BL = TK_TG_SCRN
;		   Not used		if BL = TK_TG_ALL
;
;		DI = offset of worker relative to caller's CS
;
;		DX,BP,DS may be used for parameter input to the worker
;		CX may also be used if BL = TK_TG_ALL
;
;	EXIT	CF Clear  The scan completed normally
;		   Set	  The scan terminated because of invalid parameters,
;
;	NOTE:	The setting of CF on exit from ScanTasks should not be confused
;		with the setting of CF on return from the final call of the
;		worker routine.  The latter is not preserved.
;
;		AX = Error Code from ScanTasks if CF set
;		   = Result code from final call of the worker if CF clear
;		     and worker terminated the scan.
;
;		     The following errors are returned from ScanTasks
;
;		     ERROR_INVALID_PROCID - The specified id is not a valid
;					    process id or command tree id
;
;		     ERROR_NOT_DESCENDANT - The specified id is a valid
;					    command tree id, but the command
;					    tree is not a command subtree of
;					    current process.
;
;		BL,CX,DX,DS - As left by the final call of the worker, if any
;			      otherwise undefined.
;
;	USES	AX,BX,ES,Flags plus any registers modified by the worker
;

Procedure ScanTasks,near
LocalVar callersBP,BP
LocalVar cregs,<SIZE CallerRegs>
	EnterProc
	mov	cregs.C_CS,0			; indicate near worker
st1:	push	si
	mov	ax,callersBP
	mov	cregs.C_BP,ax			; Save user's registers
	mov	cregs.C_DS,ds
	mov	cregs.C_DX,dx
	mov	cregs.C_CX,cx
	mov	cregs.C_DI,di			; worker address
	lea	eax,cregs			; tkScanWorker uses ss:cregs
	FlatContext <ds,es>,dx
	PushP	eax				; pValues
	PushP	<offset FLAT:tkScanWorker>	; pWorker
	movzx	eax,cx
	PushP	eax				; GroupId
	movzx	eax,bx
	PushP	eax				; ScanFlags
	CCALL32	_TKScanTasks,,,PushP

	mov	ds,cregs.C_DS
	mov	dx,cregs.C_DX
	mov	cx,cregs.C_CX
	mov	di,cregs.C_DI
	cmp	cregs.C_CS,0			; far caller?
	jne	stf01				; yes - use hy_ScanTasks RETP

	cmp	eax,1				; Set carry if (EAX) nonzero
	cmc
	LeaveProc
	RETP
EndProc ScanTasks


;***EP	ScanTasks - far version of scantasks
;
;	See ScanTasks above for interface specification.

Procedure ScanTasks,faronly
LocalVar cregs,<SIZE CallerRegs>
stf00:
	EnterProc
	mov	ax,[BP].RetAddr.Segmt
	mov	cregs.C_CS,ax			; indicate far worker
	jmp	short st1			; jump to common code

stf01:	cmp	eax,1				; Set carry if (EAX) nonzero
	cmc
	LeaveProc
	RETP
EndProc ScanTasks


;***LP	Scan16 - 16-bit interface routine. Called by TKScanWorker to
;	dispatch to the 16-bit worker.
;
;	ENTRY:
;		SS:DI - pointer to worker address
;			If the high word at SS:DI+2 is 0, a near call is made
;			to the worker, else a farcall is made to the worker.
;
;	EXIT:	EAX set according to carry flag
;		-1 if C set
;		 0 otherwise
	ASSUME	DS:NOTHING, ES:FLAT, SS:NOTHING

Procedure Scan16,far16
	cmp	word ptr ss:[di+2],0		; check if worker CS specified
	je	sx1				; no, it's a near call
	call	dword ptr ss:[di]		; call far worker
	jmp	short sx2
sx1:	call	word ptr ss:[di]		; call near worker
sx2:	sbb	eax,eax
	RETP
EndProc Scan16


HIGH3CODE	ENDS

	FARCODE HIGH32
_TEXT	SEGMENT

;***LP	tkScanWorker - worker routine for ScanTasks. Setup by ScanTasks and
;	called by TKScanTasks.
;
;	ENTRY:
;		pptda - pointer to ptda of interest
;		cregs - pointer to CallerRegs structure
;
;	EXIT:
;		calls supplied worker.
;
;	Pascal calling convention.

Procedure tkScanWorker,near
ArgVar	pptda,dword
ArgVar	cregs,dword
	EnterProc
	SaveReg <ds,es,ebx,esi,edi>
	push	ebp
	mov	eax,pptda
	movzx	eax,[eax].ThisPTDA
	mov	es,eax			; (ES)	- ptda selector
	mov	ebp,cregs		; (SS:EBP) - ptr to CallerRegs struct
	mov	dx,[ebp].C_DX
	mov	cx,[ebp].C_CX
	mov	ds,[ebp].C_DS
	lea	edi,[ebp].C_DI		; (EDI) - pointer to address of worker
	movzx	ebp,[ebp].C_BP		; (BP) - scantasks' callers bp
	CALL16	Scan16
	mov	ebx,ebp			; (BX) = returned BP
	pop	ebp

	push	ebp
	mov	ebp,cregs		; (SS:EBP) - ptr to CallerRegs struct
	mov	[ebp].C_DX,dx		; Set up return values
	mov	[ebp].C_CX,cx
	mov	[ebp].C_DS,ds
	mov	[ebp].C_BP,bx		; Restore saved BP
	lea	ebx,[ebp].C_DI
	cmp	bx,di			; did the worker modify DI?
	je	tsw10
	mov	[ebp].C_DI,di	; yes, reset new worker
tsw10:	pop	ebp
	RestoreReg <edi,esi,ebx,es,ds>
	LeaveProc
	RETC
EndProc tkScanWorker

_TEXT	ENDS

	END
