📄 gshare.asm
字号:
sub al,al ; don't create an entry
call FNM ; find the name gain
jnc mclo1 ; got still more
clc
; exit. 'C' and (ax) setup
;
; (TOS+2:TOS) = address of ASCIZ string
mclo9: pop si ; clean stack
pop ds
LeaveCrit critShare
ret
EndProc MFTcloN
BREAK <Set_Mult_Block - Try to set multiple locks>
;******************* START OF SPECIFICATIONS ***********************************
;
; NAME: Set_Mult_Block - Set Multiple Block Locks
;
; FUNCTION: Set_Mult_Block sets a lock on 1 or more specified ranges
; of a file. An error is returned if any lock range conflicts
; with another. Ranges of Locks are cleared via Clr_Mult_Block.
;
; In DOS 3.3 only one lock range could be set at a time using
; Set_Block. For DOS 4.00 this routine will replace Set_Block
; in the jump table and will make repeated calls to Set_Block
; in order to process 1 or more lock ranges.
;
; NOTE: - This is an all new interface to IBMDOS
;
; INPUT: (AL) = 0 - lock all
; = 80 - lock write
; (CX) = the number of lock ranges
; (DS:DX) = pointer to the range list
; (ES:DI) = SFT address
; User_ID = 16-bit user id of issuer
; Proc_ID = 16-bit process id of issuer
; (SS) = DOSData
;
; OUTPUT: Lock records filled in for all blocks specified
;
; REGISTERS USED: ALL but DS
; (NOT RESTORED)
;
; LINKAGE: IBMDOS Jump Table
;
; EXTERNAL Invoke: Load_Regs, Set_Block, Clr_Block
; REFERENCES:
;
; NORMAL 'C' clear if no error
; EXIT:
;
; ERROR 'C' set if error
; EXIT: (ax) = error code
; ('error_lock_violation' if conflicting locks)
;
; CHANGE 04/15/87 - First release
; LOG:
;
;******************* END OF SPECIFICATIONS *************************************
;******************+ START OF PSEUDOCODE +**************************************
;
; START Set_Mult_Block
;
; count = start_count
; search till count = 0
; invoke Load_Regs
; invoke Set_Block
; exit if error
; clear_count = start_count - current_count
; loop till clear_count = 0
; invoke Load_Regs
; invoke Clr_Block
; leave if error
; end loop
; set error status
; orelse
; endloop
; set successful status
; endsrch
; if error status
; load return code
; endif
; return
;
; END Set_Mult_Block
;
;******************+ END OF PSEUDOCODE +**************************************
Procedure Set_Mult_Block,NEAR
; PUSH DS ;ICE
; push bx ;ICE
; push ax ;ICE
; mov bx,0140H ;ICE
; xor ax,ax ;ICE
; mov ds,ax ;ICE
; mov ax,word ptr ds:[bx] ;ICE
; mov word ptr ds:[bx],ax ;ICE
; pop ax ;ICE
; pop bx ;ICE
; POP DS ;ICE
EnterCrit critShare ; ;AN000;
ASSUME ES:NOTHING,DS:NOTHING ; ;AN000;
; set up for loop
; WE HAVE: (from IBMDOS) | WE NEED: (for Set_Block)
; (AL) = 0 - lock all | (BX) = 0 lock all operations
; = 80- lock write | = 1 lock write operations
; (CX) = the number of lock ranges | (CX:DX) = offset of area
; (DS:DX) = pointer to the range list | (SI:AX) = length of area
; (ES:DI) = SFT address | (ES:DI) = SFT address
; int 3
nop
nop
mov DS_Org,ds ;an000;save entry DS
Context DS ; ;AN000;
CMP CX,01h ;DO WE HAVE A COUNT? ;AN000;
;; $if ae ; if the count was valid ;AN000;
; $if e ; if the count was valid ;AC006;
JNE $$IF1
;; PUSH CX ; count = start_count ;AN000;
;; PUSH DX ; save pointer to range list ;AN000;
MOV BP,DX ; save current index into list ;AN000;
;; AND AX,0080H ; clear high byte and be sure low is ;AN000;
; set if applicable
;; ROL AL,1 ; move high bit to bit 0
;; MOV BX,AX ; SET UP TYPE OF LOCK ;AN000;
;; $do ; loop till count = 0 ;AN000;
;; cmp cx,00 ;an000;see if at end
;; $leave e ;an000;exit if at end
;; push cx ;an000;save cx - our counter
;; push di ;an000;save di - our SFT pointer
call load_regs ;an000;load the registers for call
; to set_block
call set_block ;an000;set the lock block
;SR;
; This routine destroys the error code returned by set_block and returns
;lock violation in case of any error. We want to preserve the error code
;returned by set_block. So, we are going to jump directly to return point
;on an error.
;
jc $$IF4
;; pop di ;an000;restore our SFT pointer
;; pop cx ;an000;restore cx - our counter
;; $leave c ;an000;on error exit loop
;; dec cx ;an000;decrease counter
;; $enddo ;an000;end loop
;; $if c ;an000;if an error occurred
;; pop dx ;an000;restore range list pointer
;; pop ax ;an000;obtain original count
;; sub ax,cx ;an000;determine how many locks set
;; mov cx,ax ;an000;set the loop counter with count
;; mov bp,dx ;an000;set bp to point to range list
;; $do ;an000;while cx not = 0
;; cmp cx,00 ;an000;at end?
;; $leave e ;an000;yes, exit
;; push cx ;an000;save cx - our counter
;; push di ;an000;save di - our SFT pointer
;; call load_regs ;an000;load the registers for call
; to clr_block
;; call clr_block ;an000;clear the locks
;; pop di ;an000;restore our SFT pointer
;; pop cx ;an000;restore cx - our counter
;; $leave c ;an000;on error exit
;; dec cx ;an000;decrease counter
;; $enddo ;an000;
;; stc ;an000;signal an error occurred
;; $else ;an000;no error occurred in locking
;; pop ax ;an000;clear off the stack
;; pop ax ;an000; to balance it
;; clc ;an000;signal no error occurred
;; $endif ;an000;
; $else ;an000;cx was 0 - this is an error
JMP SHORT $$EN1
$$IF1:
stc ;an000;signal an error occurred
; $endif ; ;an000;
$$EN1:
; $if c ; if there was an error ;AN000;
JNC $$IF4
MOV AX,error_lock_violation ; load the return code ;AN000;
; $endif ; endif there was an error ;AN000;
$$IF4:
LeaveCrit critShare ; ;AN000;
ret ; return - all set ;AN000;
EndProc Set_Mult_Block
BREAK <Load_Regs - Load Registers for ?_Block call>
;******************* START OF SPECIFICATIONS ***********************************
;
; NAME: Load_Regs - Load Registers for ?_Block calls
;
; FUNCTION: This subroutine loads the High and Low Offsets and the
; High and Low lengths for Lock ranges from the Range List.
;
; INPUT: (DS_Org:PB) - Range list entry to be loaded
;
; OUTPUT: (DX) - Low Offset
; (CX) - High Offset
; (AX) - Low Length
; (SI) - High Length
;
; REGISTERS USED: AX CX DX BP SI
; (NOT RESTORED)
;
; LINKAGE: Called by: Set_Mult_Block, Clr_Mult_Block
;
; EXTERNAL none
; REFERENCES:
;
; NORMAL none
; EXIT:
;
; ERROR none
; EXIT:
;
; CHANGE 04/15/87 - first release
; LOG:
;
;******************* END OF SPECIFICATIONS *************************************
;******************+ START OF PSEUDOCODE +**************************************
;
; START Load_Regs
;
; recover index into range list
; advance pointer to next entry
; load DX - Low Offset
; load CX - High Offset
; load AX - Low Length
; load SI - High Length
; return
;
; END Load_Regs
;
;******************+ END OF PSEUDOCODE +**************************************
Procedure Load_Regs,NEAR
push ds ; save our DS ;an000;
mov ds,DS_Org ; get range list segment ;an000;
mov si,bp ; recover pointer ;AN000;
ADD BP,08h ; move to next entry in list ;AN000;
MOV DX,[SI] ; low position ;AN000;
MOV CX,[SI+2] ; high position ;AN000;
MOV AX,[SI+4] ; low length ;AN000;
MOV SI,[SI+6] ; high length ;AN000;
pop ds ; restore DS ;an000;
ret ; ;AN000;
EndProc Load_Regs
BREAK <Clr_Mult_Block - Try to clear multiple locks>
;******************* START OF SPECIFICATIONS ***********************************
;
; NAME: Clr_Mult_Block - Clear Multiple Block Locks
;
; FUNCTION: Clr_Mult_Block removes the locks on 1 or more specified
; ranges of a file. An error is returned if any lock range
; does not exactly match. Ranges of Locks are set via
; Set_Mult_Block.
;
; In DOS 3.3 only one lock range could be cleared at a time
; using Clr_Block. For DOS 4.00 this routine will replace
; Clr_Block in the jump table and will make repeated calls
; to Set_Block in order to process 1 or more lock ranges.
;
; NOTE: - This is an all new interface to IBMDOS
; - an unlock all 'lock all' request will unlock both
; 'lock all' and 'lock write'.
; - an unlock all 'lock write' request will not unlock
; 'lock all's. It will only unlock 'lock write's.
; (if you can understand the above statement,
; understanding the code will be easy!)
;
; INPUT: (AL) = 0 - lock all
; = 80- lock write
; (CX) = the number of lock ranges - NB: all if -1 ***
; (DS:DX) = pointer to the range list
; (ES:DI) = SFT address
; User_ID = 16-bit user id of issuer
; Proc_ID = 16-bit process id of issuer
; (SS) = DOSData
;
; OUTPUT: Lock records filled in for all blocks specified
;
; REGISTERS USED: ALL but DS
; (NOT RESTORED)
;
; LINKAGE: IBMDOS Jump Table
;
; EXTERNAL Invoke: Load_Regs, Set_Block, Clr_Block, Clr_List
; REFERENCES:
;
; NORMAL 'C' clear if no error
; EXIT:
;
; ERROR 'C' set if error
; EXIT: (ax) = error code
; ('error_lock_violation' if conflicting locks)
;
; CHANGE 04/15/87 - First release
; LOG:
;
;******************* END OF SPECIFICATIONS *************************************
;******************+ START OF PSEUDOCODE +**************************************
;
; START Clr_Mult_Block
;
; if count is valid and
; if file (SFT) is 'shared' then
; if count = all
; find first RLR
; loop till all RLR cleared
; if PROC_ID matches and
; if UID matches and
; if SFT matches then
; if ulocking lock_all or
; if this RLR is lock_write
; clear the lock
; endif
; endif
; find next RLR
; end loop
; else
; invoke Clr_List
; endif
; set successful status
; else
; set error status
; endif
; if error
; load return code
; endif
;
; ret
;
; END Clr_Mult_Block
;
;******************+ END OF PSEUDOCODE +**************************************
Procedure clr_mult_block,NEAR
lock_all equ 0h
; PUSH DS ;ICE
; push bx ;ICE
; push ax ;ICE
; mov bx,0140H ;ICE
; xor ax,ax ;ICE
; mov ds,ax ;ICE
; mov ax,word ptr ds:[bx] ;ICE
; mov word ptr ds:[bx],ax ;ICE
; pop ax ;ICE
; pop bx ;ICE
; POP DS ;ICE
EnterCrit critShare ; ;AN000;
ASSUME ES:NOTHING,DS:NOTHING ; ;AN000;
; int 3
nop
nop
mov DS_Org,DS ;an000;save entry DS
Context DS ; ;AN000;
CMP CX,01h ; do we have a count? ;AN000;
;; $IF AE,AND ; IF A VALID COUNT
; $IF E,AND ; IF A VALID COUNT ;AC006;
JNE $$IF6
cmp es:[di].sf_mft,0 ; is this SFT shared? ;AN000;
; $IF NE ; AND IF FILE IS 'SHARED' THEN
JE $$IF6
; WE HAVE: (from IBMDOS) | WE NEED:
; (AL) = 0 - lock all | (AX) = 0 lock all operations
; = 80- lock write | = 1 lock write operations
; (CX) = - 1 (unlock all locks) | (DS) = CS
; | (DS:DI) = previous RLR
; | (DS:SI) = current RLR
; (ES:DI) = current SFT |
;; and ax,0080h ;be sure it is set right (mask 80 bit) ;AC002;
; existing interface
;; rol al,1 ;put high bit in bit 0 ;AC002;
;; CMP CX,-1h ; ;AN000;
;; $IF E ; IF unlock all locks then ;AN000;
;; push cs ; ;AN000;
;; pop ds ; ;AN000;
;; mov cx,di ; ES:CX is the SFT ;AN004;
; ASSUME ds:nothing
;; mov si,es:[di].sf_mft ; DS:SI points to MFT ;AN000;
;; lea di,[si].mft_lptr ; DS:DI = addr of ptr to lock record ;AN000;
;; mov si,[di] ; DS:SI = address of 1st lock record ;AN000;
;; $DO ; loop through the RLR's ;AN000;
; DS:DI = points to previous RLR or MFT if no RLR.
; DS:SI = points to current RLR
; ES:CX = SFT address
; AX = lock type
;; and si,si ; are we at the end of the chain? ;AN000;
;; $LEAVE Z ; we'er done with CF = 0 ;AN000;
;; mov bp,[si].rlr_pid ; get PROC_ID ;AN000;
;; cmp bp,PROC_ID ; is it ours? ;AN000;
;; $IF E,AND ; ;AN000;
;; mov bp,es ; ;AN000;
;; cmp bp,WORD PTR [si].rlr_sptr+2 ; ;AC004;
;; $IF E,AND ; ;AN000;
;; cmp cx,WORD PTR [si].rlr_sptr ; ;AC004;
;; mov si,[di] ; restore pointer to current (using ;AN000;
; previous)
;; $IF E ; if it is ours ;AN000;
; this is it. its OURS !
;; cmp ax,lock_all ; ;AN000;
;; $IF E,OR ; if unlocking all or ;AN000;
;; mov bp,[si].rlr_type ; get lock type ;AN000;
;; cmp bp,rlr_lall ; is it lock all? ;AN000;
;; $IF NE ; if not a LOCK ALL lock ;AN000;
; remove the RLR from the chain
;; mov bx,[si].rlr_next ; get the pointer to the next RLR ;AN000;
;; mov [di],bx ; install it in the last ;AN000;
; put defunct lock record on the free chain
;; mov bx,Frelock ; ;AN000;
;; mov [si].rlr_next,bx ; ;AN000;
;; mov Frelock,si ; ;AN000;
;; mov si,di ; back up to last ;AN000;
;; $ENDIF ; should we unlock it ;AN000;
;; $ENDIF ; it was ours! ;AN000;
; advance to next RLR
;; mov di,si ; load address of next RLR ;AN000;
;; mov si,[di] ; update pointer to next RLR ;AN000;
;; $ENDDO ; loop back to the start ;AN000;
;; $ELSE ; else, its a LIST ! ;AN000;
; set up for loop
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -