⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gshare.asm

📁 Dos6.0
💻 ASM
📖 第 1 页 / 共 5 页
字号:
   EndProc ASC


   BREAK <BCS - Bulk Close of SFTs>

;******************* START OF SPECIFICATIONS ***********************************
;
;	BCS - Bulk Close of SFTs
;
;	BCS scans the MFT structures looking for SFTs that match a UID (and
;	perhaps a PID).  The SFTs are closed.  The MFT name record is removed
;	if all its SFTs are closed.
;
;	BCS is called with a PID and a PID MASK.  The SFT is closed if its UID
;	matches the supplied UID AND (PID_ & PIDMASK) == PID_supplied
;
;	We walk the MFT structure closing all relevant SFT's. There is no
;	need for special handling of 70 handles or FCBs.
;
;	Note that we call DOS_close to close the SFT; DOS_close in turn calls
;	mftclose which may remove the SFT and even the MFT.  This means that
;	the MFT may vanish as we are working on it.  Whenever we call
;	DOS_close we'll know the next SFT and, if there is no next SFT we'll
;	know the next MFT.  (If the MFT were released a pointer to the carcass
;	is not of any help.  An MFT carcass cannot help find the next MFT
;	record)
;
;	ENTRY	(AX) = UID to match
;		(BX) = PID mask
;		(DX) = PID value
;	EXIT	'C' clear
;	USES	ALL
;
;******************* END OF SPECIFICATIONS *************************************

   ASSUME SS:DOSDATA

   Procedure BCS,NEAR

   push cs
   pop	ds

   Off	SI,mft				; start at beginning of buffer

;	scan forward to the nearest name record (we may be at it now)
;
;	(DS:SI) = record pointer

bcs1: cmp [si].mft_flag,MFLG_FRE
   jl	bcs16				; at end of names, all done
   jg	bcs2				; have a name record

bcs1$5: add si,[si].mft_len		; skip record and loop
   jmp	bcs1

bcs16: jmp short bcs9

bcs2: les di,[si].mft_sptr		; got name record - get first SFT
;	run down SFT chain
;
;	(es:di) = FBA next SFT
;	(ds:si) = FBA name record
;	(ax) = UID to match
;	(bx) = PID mask
;	(dx) = PID value

bcs3: or di,di
   jz	bcs1$5				; at end of SFT chain
   cmp	ax,es:[di].sf_UID
   jnz	bcs4				; not a match
   mov	cx,es:[di].sf_PID
   and	cx,bx				; apply mask
   cmp	cx,dx
   jz	bcs51				; got a match
bcs4:
   les	di,es:[di].sf_chain
   JMP	bcs3				; chain to next SFT


;	We have an SFT to close
;
;	(es:di) = FBA SFT to be closed
;
;	(ds:si) = FBA name record
;	(ax) = UID to match
;	(bx) = PID mask
;	(dx) = PID value

bcs51: mov es:[di].sf_ref_count,1
   push ax
   push bx
   push dx				; save ID values (ax,bx,dx) and mask
   push ds
   push si				; save name record address (ds:si)
   mov	si,word ptr es:[di].sf_chain
   or	si,si
   jnz	bcs7				; isnt last sft, MFT will remain

;	yup, this is the last sft for this MFT, the MFT may evaporate.	we have
;	to find the next one NOW, and remember it

   pop	si				; undo saved name record address
   pop	ds
bcs6: add si,[si].mft_len		; go to next guy
   cmp	[si].mft_flag,MFLG_FRE
   jz	bcs6				; must be a non-free guy
   push ds
   push si				; resave our new next MFT
   sub	si,si				; no next sft

;	Allright, we're ready to call the DOS.
;
;	(es:di)     = FBA sft to be closed
;	((sp))	 = long address of current or next MFT
;	((sp)+4) = PID value
;	((sp)+6) = PID mask
;	((sp)+8) = UID value

bcs7: mov WORD PTR ThisSFT,di
   mov	WORD PTR ThisSFT+2,es
   mov	es,word ptr es:[di].sf_chain+2
   SaveReg <es,si>
   call CPS				; clear JFN
   Context DS

   CallInstall DOS_Close,multDos,1

   ASSUME DS:NOTHING

   RestoreReg <di,es>			; (es:DI) = offset of next sft
   pop	si
   pop	ds				; (DS:SI) = fwa of current or next MFT
   pop	dx
   pop	bx
   pop	ax
   or	di,di
   jnz	bcs85				; have more sft's
   JMP	bcs1				; look at this new MFT
bcs85: jmp bcs3

;	All Done

bcs9: clc

   ret

   EndProc BCS

   BREAK <CSL - Clear SFT Locks>

;******************* START OF SPECIFICATIONS ***********************************
;
;	CSL - Clear SFT Locks
;
;	CSL clears any locks associated with this SFT.
;
;	ENTRY	(ES:DI) = SFT address
;	EXIT	(ES:DI) unchanged
;	USES	All but ES,DI
;
;******************* END OF SPECIFICATIONS *************************************

   Procedure CSL,NEAR

   mov	si,es:[di].sf_MFT
   push cs
   pop	ds
   lea	bx,[si].mft_lptr		; (DS:BX) = addr of lock ptr
   mov	si,[bx] 			; (DS:SI) = fba first lock record

;	scan the locks looking for belongers.
;
;	(es:di) = SFT address
;	(ds:si) = this lock address
;	(ds:bx) = address of link (offset value) to this lock (prev lock)

csl1: or si,si
   jz	csl3				; done with lock list
   cmp	di,word ptr [si].rlr_sptr
   jnz	csl2				; not my lock
   mov	ax,es
   cmp	ax,word ptr [si].rlr_sptr+2
   jnz	csl2				; not my lock
;
; Make sure that the lock REALLY belongs to the correct process
;
   cmp	user_in_ax, (ServerCall shl 8) + 4 ; only check if   ; @@01
   jnz	csl15				; process specific; @@01
   mov	ax,Proc_ID
   cmp	ax,[si].rlr_pid 		; is process ID of lock = this PID?
   jnz	csl2				; nope, skip this lock

;	got a lock to remove

csl15:
   mov	dx,[si].rlr_next
   mov	[bx],dx 			; link him out
   mov	ax,Frelock
   mov	[si].rlr_next,ax
   mov	Frelock,si
   mov	si,dx				; (DS:SI) = next lock address
   JMP	SHORT csl1

   ERRNZ rlr_next			; lock is not ours... follow chain
csl2: mov bx,si
   mov	si,[si].rlr_next
   JMP	SHORT csl1

;	All done

csl3: ret

   EndProc CSL

   ASSUME DS:NOTHING

   BREAK <CUC - check usage conflicts>

;******************* START OF SPECIFICATIONS ***********************************
;
;	Use conflict table
;
;	Algorithm:
;
;		if ((newmode == COMPAT) or (oldmode == COMPAT))
;			and (user ID's match)
;		   then accept
;		else
;		for new and old mode, compute index of (SH*3)+ACC
;		shift right table[new_index] by old_index+2;
;			'C' set if FAIL
;
;	The bit in the old_index position indicates the success or failure.  0
;	=> allow access, 1 => fail access
;
;******************* END OF SPECIFICATIONS *************************************

   PUBLIC CUCA

CUCA: DW 0ffffh 			; Compat    Read
   DW	0ffffh				; Compat    Write
   DW	0ffffh				; Compat    Read/Write
   DW	0ffffh				; Deny R/W  Read
   DW	0ffffh				; Deny R/W  Write
   DW	0ffffh				; Deny R/W  Read/Write
   DW	0df7fh				; Deny W    Read
   DW	0dbffh				; Deny W    Write
   DW	0dfffh				; Deny W    Read/Write
   DW	0beffh				; Deny R    Read
   DW	0b7ffh				; Deny R    Write
   DW	0bfffh				; Deny R    Read/Write
   DW	01c7fh				; Deny None Read
   DW	003ffh				; Deny None Write
   DW	01fffh				; Deny None Read/Write

;					     4443 3322 2111 000
;   Deny/Compat 			/    DDDD DDDD DDDD CCCx
;   DenyRead			       /	R RR	RRR
;   DenyWrite		  1st Access =< 	    WW WWWW
;   AccessRead			       \     R RR  RR  RR R R R
;   AccessWrite 			\    WW W W WW	WW  WW
;   x					     1111 1111 1111 1111
;   C  R    00				     1111 1111 1111 1111  ffff
;   C	W   01				     1111 1111 1111 1111  ffff
;   C  RW   02				     1111 1111 1111 1111  ffff

;   DRWR    10				     1111 1111 1111 1111  ffff
;   DRW W   11				     1111 1111 1111 1111  ffff
;   DRWRW   12				     1111 1111 1111 1111  ffff
;   D WR    20				     1101 1111 0111 1111  df7f

;   D W W   21				     1101 1011 1111 1111  dbff
;   D WRW   22				     1101 1111 1111 1111  dfff
;   DR R    30				     1011 1110 1111 1111  beff
;   DR	W   31				     1011 0111 1111 1111  b7ff

;   DR RW   32				     1011 1111 1111 1111  bfff
;   D  R    40				     0001 1100 0111 1111  1c7f
;   D	W   41				     0000 0011 1111 1111  03ff
;   D  RW   42				     0001 1111 1111 1111  1fff

;   In order to allow the greatest number of accesses, compatability read mode
;   is treated as deny-write read.  The other compatability modes are treated
;   as deny-both.

;******************* START OF SPECIFICATIONS ***********************************
;
;	CUC - check usage conflicts
;
;	CUC is called to see if a would-be open would generate a share
;	conflict with an existing open.  See CUCA for the algorithm and table
;	format.
;
;	ENTRY	(BX) = FBA MFT name record
;		(DS:SI) = SFT address
;	EXIT	'C' clear if OK
;		'C' set if conflict
;		  (ax) = error code
;	USES	ALL but arguments (BX, DS:SI)
;
;******************* END OF SPECIFICATIONS *************************************

   Procedure CUC,NEAR

   push ds
   pop	es
   mov	di,si				; (es:di) = FBA SFT record
   call gom				; get open mode
   mov	ch,al
   and	ch,sharing_mask 		; (ch) = new guy share
   jz	cuc0				; new guy is compatability mode
   mov	ch,sharing_mask
cuc0: call csi				; compute share index
   add	ax,ax				; *2 for word index
   xchg ax,si				; (si) = share table index
   push cs
   pop	ds				; (ds:bx) = FBA MFT record
   mov	dx,WORD PTR CUCA[si]		; (dx) = share mask
   lds	si,[bx].mft_sptr		; (ds:si) = first sft guy

;	ready to do access compares.
;
;	(ds:si) = address of next sft
;	(es:di) = address of new  sft
;	(dx) = share word from CUCA
;	(cs:bx) = MFT offset
;	(ch) = 0 if new SFT is compatibilty mode, else sharing_mask

cuc1: or si,si
   jz	cuc9				; at end of chain, no problems
   call gom				; if not FCB, then mode in al is good
   mov	ah,al
   and	ah,sharing_mask 		; (ah) = sharing mode
   or	ah,ch				; (ah) = 0 iff new and old is SH_COMP
   jnz	cuc2				; neither is SH_COMP

;	Both the old and the new guy are SH_COMP mode.	If the UIDs match,
;	step onward.  If they don't match do normal share check.

   mov	bp,es:[di].sf_UID
   cmp	bp,[si].sf_UID
   jz	cuc20				; equal => next sft to check

cuc2: call csi				; compute the share index
   inc	ax
   inc	ax
   xchg al,cl				; (cl) = shift count
   mov	ax,dx
   sar	ax,cl				; select the bit
   jc	cuc8				; a conflict!
cuc20:
   lds	si,[si].sf_chain
   JMP	cuc1				; chain to next SFT and try again

;	Have a share conflict

cuc8: mov ax,error_sharing_violation	; assume share conflict
   stc

;	done with compare.  Restore regs and return
;
;	'C' set as appropriate
;	(es:di) = new SFT address
;	(ax) set as appropriate
;	(bx) = MFT offset

cuc9: push es
   pop	ds
   mov	si,di

   ret

   EndProc CUC

   BREAK <csi - compute share index>

;******************* START OF SPECIFICATIONS ***********************************
;
;	csi - compute share index
;
;
;	If the mode byte has a leading 7 then it is interpreted as a 0
;	csi turns a mode byte into an index from 0 to 14:
;
;		(share index)*3 + (access index)
;
;	ENTRY	(al) = mode byte
;	EXIT	(ax) = index
;	USES	AX, CL
;
;******************* END OF SPECIFICATIONS *************************************

   Procedure CSI,NEAR

   mov	ah,al
   and	ah,access_mask			; (ah) = access bits
   and	al,sharing_mask 		; (al) = share bites
   ERRNZ sharing_mask-0F0h
   cmp	al,sharing_net_FCB
   jnz	csi1
   xor	al,al
csi1:
   shr	al,1
   shr	al,1
   shr	al,1
   mov	cl,al				; (cl) = SHVAL*2
   shr	al,1
   add	al,cl				; (al) = SHVAL*3
   add	al,ah				; (al) = SH*3 + ACC
   sub	ah,ah

   ret

   EndProc CSI

   Break <GOM - get open mode>

;******************* START OF SPECIFICATIONS ***********************************
;
;	GOM - get open mode
;
;   Find the correct open mode given the encoded sf_mode.  Note that files
;   marked READ-ONLY and are opened in compatability read-only are treated as
;   deny-write read-only.  FCB opens are sharing_compat open_for_both and
;   net FCB opens are sharing_compat
;
;	Entry:	    (DS:SI) points to SFT
;   Exit:	(AL) has correct mode
;   Uses:	(AX)
;******************* END OF SPECIFICATIONS *************************************

   Procedure GOM,NEAR

   mov	ax,[si].sf_mode
   TEST AX,sf_IsFCB
   jz	gom1				; if not FCB, then mode in al is good
   mov	al,sharing_compat+open_for_both
gom1:
   mov	ah,al
   and	ah,sharing_mask
   cmp	ah,sharing_net_FCB		; is sharing from net FCB?
   jnz	gom2				; no, got good mode
   and	al,access_mask			; yes, convert to compat mode sharing
   or	al,sharing_compat
;
; The sharing mode and access mode in AL is now correct for the file.  See if
; mode is compatability.  If so and file is read-only, convert access mode to
; deny-write read.
;
gom2:
   mov	ah,al
   and	ah,sharing_mask
   retnz				; not compatability, return.
   test [si].sf_attr,attr_read_only
   retz 				; not read-only
   mov	al,sharing_deny_write + open_for_read

   ret

   EndProc GOM

   SHARE ENDS

   END
   ELSE
CODE ENDS
   ENDIF
   END					; This can't be inside the if
; mode is compatability.  If so and file is read-only, convert access mode to
; deny-write read.
;
gom2:
   mov	ah,al
   and	ah,sharing_mask
   retnz				; not compatability, return.
   test [si].sf_attr,attr_read_only
   retz 				; not read-only
   mov	al,sharing_deny_write + open_for_read

   ret

   EndProc GOM

   SHARE ENDS

   END
   ELSE
CODE ENDS
   ENDIF
   END					; This can't be inside the if

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -