📄 gshare.asm
字号:
Title Share_1
;/*
; * Microsoft Confidential
; * Copyright (C) Microsoft Corporation 1991
; * All Rights Reserved.
; */
; $SALUT (0,36,41,44)
include SHAREHDR.INC
;
; Label: "The DOS SHARE Utility"
;
;******************* END OF SPECIFICATIONS *************************************
;
; Revision History
; ================
;
; M001 SR 9/10/90 Removed /NC support -- 'skip_check'
; references.
;
; M003 SR 10/1/90 Bug #2425 fixed. In ASC, check if the
; SFT to be chained is the same as the
; current SFT. Dont chain if so.
;
extrn fnm:near, rsc:near, rmn:near, cps:near, ofl:near, sle:near, interr:near
NAME Sharer
.xlist
.xcref
include sf.inc
include filemode.inc
include mult.inc
include syscall.inc
INCLUDE DOSSYM.INC
include dpl.asm
.cref
.list
AsmVars <IBM, Installed>
Installed = TRUE ; for installed version
OFF Macro reg,val
IF installed
mov reg,OFFSET val
ELSE
mov si,OFFSET DOSGROUP:val
ENDIF
ENDM
ERRNZ Macro x
IF x NE 0
%out ERRNZ failed
ENDIF
ENDM
; if we are installed, then define the base code segment of the sharer first
IF Installed
Share SEGMENT PARA PUBLIC 'SHARE'
Share ENDS
include dosseg.inc
; include the rest of the segment definitions for normal msdos
; We CANNOT include dosseg because start is not declared para in that file
; $SALUT (4,9,17,36)
;START SEGMENT PARA PUBLIC 'START'
;START ENDS
;CONSTANTS SEGMENT WORD PUBLIC 'CONST'
;CONSTANTS ENDS
;DATA SEGMENT WORD PUBLIC 'DATA'
;DATA ENDS
;TABLE SEGMENT BYTE PUBLIC 'TABLE'
;TABLE ENDS
;CODE SEGMENT BYTE PUBLIC 'CODE'
;CODE ENDS
;LAST_SEG SEGMENT PARA PUBLIC 'LAST_SEG'
;LAST_SEG ENDS
;DOSGROUP GROUP START,CONSTANTS,DATA,TABLE,CODE,LAST_SEG
ELSE
include dosseg.asm
ENDIF
DOSDATA SEGMENT WORD PUBLIC 'DATA'
Extrn ThisSFT:DWORD ; pointer to SFT entry
Extrn User_ID:WORD
Extrn Proc_ID:WORD
Extrn WFP_START:WORD
Extrn BytPos:DWORD
extrn OpenBuf:BYTE
extrn user_in_ax:WORD
IF debug
Extrn BugLev:WORD
Extrn BugTyp:WORD
include bugtyp.asm
ENDIF
DOSDATA ENDS
; if we are not installed, then the code here is just part of the normal
; MSDOS code segment otherwise, define our own code segment
.sall
IF NOT INSTALLED
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME SS:DOSGROUP,CS:DOSGROUP
ELSE
Share SEGMENT PARA PUBLIC 'SHARE'
ASSUME SS:DOSDATA,CS:SHARE
ENDIF
extrn MFT:BYTE
;SR;
; This message is now defined in another file for internationalization
;purposes.
;
extrn AscErr:BYTE
include mft.inc
PUBLIC FreLock,Serial
IF installed
Frelock DW ? ; FWA of lock free list
ELSE
Frelock DW OFFSET DOSDATA:lck8 ; FWA of lock free list
ENDIF
Serial DW 0 ; serial number
DS_Org dw 0 ;an000;DS on entry to routine
ZERO EQU 0
ONE EQU 1
FRAME struc
SavedBP dw ?
RetOFF dw ?
Parm_1 dw ?
Parm_2 dw ?
FRAME ends
; $SALUT (4,4,9,41)
BREAK <Sharer - MultiProcess File Sharer>
;******************* START OF SPECIFICATIONS ***********************************
;
; MSDOS MFT Functions
;
; The Master File Table (MFT) associates the cannonicalized pathnames,
; lock records and SFTs for all files open on this machine.
;
; These functions are supplied to maintain the MFT and extract
; information from it. All MFT access should be via these routines so
; that the MFT structure can remain flexible.
;
;******************* END OF SPECIFICATIONS *************************************
BREAK <Mft_enter - Make an MFT entry and check access>
;******************* START OF SPECIFICATIONS ***********************************
;
; mft_enter - make an entry in the MFT
;
; mft_enter is called to make an entry in the MFT.
; mft_enter checks for a file sharing conflict:
; No conflict:
; A new MFT entry is created, or the existing one updated,
; as appropriate.
; Conflicts:
; The existing MFT is left alone. Note that if we had to
; create a new MFT there cannot be, by definition, sharing
; conflicts.
; If no conflict has been discovered, the SFT list for the file is
; checked for one that matches the following conditions:
;
; If mode == 70 then
; don't link in SFT
; increment refcount
; If mode&sfIsFCB and userids match and process ids match then
; don't link in SFT
;
; ENTRY ThisSFT points to an SFT structure. The sf_mode field
; contains the desired sharing mode.
; WFP_Start is an offset from DOSData of the full pathname for
; the file
; User_ID = 16-bit user id of issuer
; Proc_ID = 16-bit process id of issuer
; (DS) = (SS) = DOSData
; EXIT 'C' clear if no error'
; 'C' set if error
; (ax) = error code
; USES ALL but DS
;
;******************* END OF SPECIFICATIONS *************************************
Procedure mft_enter,NEAR
; int 3
nop
nop
EnterCrit critShare
DOSAssume SS <DS>,"MFT_Enter entry"
ASSUME ES:NOTHING,SS:DOSDATA
push ds
; find or make a name record
mov si,WFP_Start ; (DS:SI) = FBA of file name
mov al,1 ; allow creation of MFT entry
push es
ASSUME DS:NOTHING
call FNM ; find or create name in MFT
pop es
mov ax,error_sharing_buffer_exceeded
jc ent9 ; not enough space
;
; (bx) = fwa name record
;
lds si,ThisSFT
call ASC ; try to add to chain
; As noted above, we don't have to worry about an "empty" name record
; being left if ASC refuses to add the SFT - ASC cannot refuse if we had
; just created the MFT...
; return.
;
; 'C' and (Ax) setup appropriately
ent9: pop ds
LeaveCrit critShare
ret
EndProc mft_enter
BREAK <MftClose - Close out an MFT for given SFT>
;******************* START OF SPECIFICATIONS ***********************************
;
; MFTclose
;
; MFTclose(SFT)
;
; MFTclose removes the SFT entry from the MFT structure. If this was
; the last SFT for the particular file the file's entry is also removed
; from the MFT structure. If the sharer is installed after some
; processing has been done, the MFT field of the SFTs will be 0; we must
; ignore these guys.
;
; If the sft indicates FCB, we do nothing special. The SFT behaves
; EXACTLY like a normal handle.
;
; If the sft indicates mode 70 then we do nothing special. These are
; normal HANDLES.
;
; Note that we always care about the SFT refcount. A refcount of 1
; means that the SFT is going idle and that we need to remove the sft
; from the chain.
;
; ENTRY (ES:DI) points to an SFT structure
; (DS) = (SS) = DOSData
; EXIT NONE
; USES ALL but DS, ES:DI
;
;******************* END OF SPECIFICATIONS *************************************
Procedure MFTclose,NEAR
; int 3
nop
nop
EnterCrit critShare
DOSAssume SS,<DS>,"MFTClose entry"
ASSUME ES:NOTHING
mov ax,es:[di].sf_MFT
fmt TypShare,LevShEntry,<"MFTClose by $x:$x of $x:$x ($x)\n">,<User_ID,Proc_id,ES,DI,AX>
or ax,ax
jz mcl10 ; No entry for it, ignore (carry clear)
push ds
push es
push di
;;;call CSL ; clear SFT locks ;AC008;
ASSUME DS:NOTHING
mov ax,es:[di].sf_ref_count ; (ax) = ref count
;
; We need to release information in one of two spots. First, when the SFT has
; a ref count of 0. Here, there are no more referents and, thus, no sharing
; record need be kept. Second, the ref count may be -1 indicating that the
; sft is being kept but that the sharing information is no longer needed.
; This occurs in creates of existing files, where we verify the allowed
; access, truncate the file and regain the access. If the truncation
; generates an error, we do NOT want to have the access locked down.
;
OR AX,AX
jz mcl85 ; ref count is 0 - don't dechain
inc ax ; -1 + 1 = 0. Busy sft.
jnz mcl9
mcl85:
call CSL ; clear SFT locks ;AC008;
call RSC ; remove sft from chain
jnz mcl9 ; not the last sft for this name
call RMN ; remove name record
mcl9:
pop di ; restore regs for exit
pop es
pop ds
mcl10:
LeaveCrit critShare
ret
EndProc MFTclose
BREAK <MftClU - Close out all MFTs for given UID>
;******************* START OF SPECIFICATIONS ***********************************
;
; MFTcloseU
;
; MFTcloseM(UID)
;
; MFTcloseM removes all entrys for user UID from the MFT structure. We
; walk the MFT structure closing all relevant SFT's for the user.
; We do it the dumb way, iterating closes until the SF ref count is
; 0.
;
; ENTRY User_ID = 16-bit user id of issuer
; (SS) + DOSData
; EXIT 'C' clear
; USES ALL
;
;******************* END OF SPECIFICATIONS *************************************
Procedure MFTclU,NEAR
; int 3
nop
nop
ASSUME DS:NOTHING,ES:NOTHING,SS:DOSDATA
EnterCrit critShare
mov ax,User_ID
fmt TypShare,LevShEntry,<"\nCloseUser $x\n">,<AX>
sub bx,bx ; insensitive to PID
sub dx,dx
invoke BCS ; bulk close the SFTs
LeaveCrit critShare
return
EndProc MFTclU
BREAK <MftCloseP - Close out all MFTs for given UID/PID>
;******************* START OF SPECIFICATIONS ***********************************
;
; MFTcloseP
;
; MFTcloseP(PID, UID)
;
; MFTcloseP removes all entrys for process PID on machine MID from the
; MFT structure. We walk the MFT structure closing all relevant
; SFT's. Do it the dumb way by iterating closes until the SFTs
; disappear.
;
; ENTRY (SS) = DOSDATA
; User_ID = 16-bit user id of issuer
; Proc_ID = 16-bit process id of issuer
; EXIT 'C' clear
; USES ALL
;
;******************* END OF SPECIFICATIONS *************************************
Procedure MFTcloseP,NEAR
; int 3
nop
nop
ASSUME DS:NOTHING,ES:NOTHING,SS:DOSDATA
EnterCrit critShare
mov ax,User_ID
mov bx,-1
mov dx,Proc_ID
fmt TypShare,LevShEntry,<"\nClose UID/PID $x:$x\n">,<AX,DX>
call BCS ; Bulk close the SFTs
LeaveCrit critShare
ret
EndProc MFTcloseP
BREAK <MftCloN - Close file by name>
;******************* START OF SPECIFICATIONS ***********************************
;
; MFTcloseN
;
; MFTcloseN(name)
;
; MFTcloseN removes all entrys for the given file from the MFT
; structure.
;
; NOTE: this function is used infrequently and need not be fast.
; (although for typical use it's not all that slow...)
;
; ENTRY DS:SI point to dpl.
; (SS) = DOSData
; EXIT 'C' clear if no error
; 'C' set if error
; AX = error_path_not_found if not currently open
; USES ALL
;
;******************* END OF SPECIFICATIONS *************************************
Procedure MFTcloN,NEAR
; int 3
nop
nop
ASSUME SS:DOSDATA,ES:NOTHING,DS:NOTHING
EnterCrit critShare
MOV DX,[SI.DPL_DX]
MOV DS,[SI.DPL_DS]
mov si,dx ; (DS:SI) = fwa name
sub al,al ; don't create if not found
push ds
push si
call FNM ; find name in MFT
mov ax,error_path_not_found ; assume error
jc mclo9 ; not found exit
; Name was found. Lets yank the SFT entrys one at a time.
mclo1: les di,[bx].mft_sptr ; (ES:DI) = SFT address
mov WORD PTR ThisSFT,di
mov WORD PTR ThisSFT+2,es ; point to SFT
cmp es:[di].sf_ref_count,1
jnz mclo15
call CPS
mclo15:
Context DS
IF installed
MOV AX,(multDOS SHL 8) + 1
INT 2FH
ELSE
call DOS_Close
ENDIF
mclo2:
ASSUME DS:NOTHING
pop si
pop ds
push ds
push si
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -