📄 gshare2.asm
字号:
Title Share_2
;/*
; * Microsoft Confidential
; * Copyright (C) Microsoft Corporation 1991
; * All Rights Reserved.
; */
;
; Revision History
; ================
;
; M000 SR 08/03/90 Fixed ShComndParse so that it exits
; after displaying help text on a
; Share /?
;
; M001 SR 9/10/90 Removed all /NC support from the code
; and rewrote the init code to not use
; all the special Share int 2fh calls.
;
; M002 SR 9/26/90 Bug #3013. The installed message and
; parse error message had identical
; message numbers. Also check the class.
;
; M004 HKN 10/18/90 To determine whether the SFT is a
; net SFT or a device we must check
; the sf_flags. bug #3584
;
; M005 SR 10/16/90 Bug #2914. Changed to ignore the /NC
; switch instead of making it an
; invalid switch.
;
; M006 SR 10/22/90 Bug #3583. Changed parsing to check
; for multiple occurrences of a switch
; and give out an error message. Share
; still continues to load and uses the
; parameter value first specified.
;
; M007 SR 11/16/90 Bug #4240. Added check to ShareInit
; to look for switcher and fail to load
; if switcher is present.
;
include SHAREHDR.INC
;
; Label: "The DOS SHARE Utility"
;
;******************* END OF SPECIFICATIONS *************************************
NAME Sharer2
; INCLUDE DOSSYM.INC
; INCLUDE SYSMSG.INC
.xlist
.xcref
INCLUDE DOSSYM.INC
INCLUDE SYSMSG.INC
include filemode.inc
include arena.inc
include cpmfcb.inc
include sf.inc
include pdb.inc
include sysvar.inc
include syscall.inc
include mult.inc
include version.inc
include vector.inc
include int2a.inc
.cref
.list
page 80,132
MSG_UTILNAME <SHARE>
ShareDataVersion = 1
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
;---------------------------------------
; $SALUT (4,9,17,36)
IF Installed
Share SEGMENT BYTE PUBLIC 'SHARE'
Share ENDS
include dosseg.inc
ENDIF
;---------------------------------------
; include the rest of the segment
; definitions for normal msdos
; segment ordering for MSDOS
;---------------------------------------
DOSDATA SEGMENT
extrn DataVersion:BYTE ; version number of DOS data.
extrn JShare:BYTE ; location of DOS jump table.
extrn sftFCB:DWORD ; [SYSTEM] pointer to FCB cache table
extrn KeepCount:WORD ; [SYSTEM] LRU count for FCB cache
extrn CurrentPDB:WORD
extrn ThisSFT:DWORD ; pointer to SFT entry
extrn WFP_start:WORD ; pointer to name string
extrn User_ID:WORD
extrn Proc_ID:WORD
extrn SFT_addr:DWORD
extrn Arena_Head:WORD
extrn fshare:BYTE
extrn pJFN:DWORD
extrn JFN:WORD
IF DEBUG
extrn BugLev:WORD
extrn BugTyp:WORD
include bugtyp.inc
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:DOSCODE
ELSE
Share SEGMENT BYTE PUBLIC 'SHARE'
ASSUME SS:DOSDATA,CS:SHARE
ENDIF
Extrn FreLock:WORD,Serial:WORD
Extrn MFT_Enter:NEAR,MFTClose:NEAR,MFTClu:NEAR,MFTCloseP:NEAR
Extrn MFTCloN:NEAR
Extrn Set_Mult_Block:NEAR,Clr_Mult_Block:NEAR,Chk_Block:NEAR
Extrn MFT_Get:NEAR
include mft.inc
; $SALUT (4,4,9,41)
BREAK <FNM - Find name in MFT>
;******************* START OF SPECIFICATIONS ***********************************
;
; FNM - Find name in MFT
;
; FNM searches the MFT for a name record.
;
; ENTRY (DS:SI) = pointer to name string (.asciz)
; (al) = 1 to create record if non exists
; = 0 otherwise
; EXIT 'C' clear if found or created
; (DS:BX) = address of MFT name record
; 'C' set if error
; If not to create, item not found
; (DS:SI) unchanged
; If to create, am out of space
; (ax) = error code
; USES ALL
;
;******************* END OF SPECIFICATIONS *************************************
Procedure FNM,NEAR
push ds ; save string address
push si
xchg bh,al ; (bh) = create flag
or bh,bh ; if not creating
jz fnm01 ; skip sft test
;---------------------------------------
; run down through string counting
; and summing
;---------------------------------------
fnm01: sub dx,dx ; (dx) = byte count
sub bl,bl ; (bl) = sum
fnm1: lodsb ; (al) = next char
add bl,al
adc bl,0
inc dx
and al,al
jnz fnm1 ; terminate after null char
;---------------------------------------
; Info computed.
; Start searching name list
; (bh) = create flag
; (bl) = sum byte
; (dx) = byte count
; (TOS+2:TOS) = name string address
;---------------------------------------
push cs
pop ds
Off SI,mft
fnm2: cmp [si].mft_flag,MFLG_FRE
jl fnm10 ; at end - name not found
jz fnm4 ; is free, just skip it
cmp bl,[si].mft_sum ; do sums compare?
jz fnm5 ; its a match - look further
fnm4: add si,[si].mft_len ; not a match... skip it
JMP SHORT fnm2
;---------------------------------------
; name checksums match
; - compare the actual strings
;
; (dx) = length
; (ds:si = MFT address
; (bh) = create flag
; (bl) = sum byte
; (dx) = byte count
; (TOS+2:TOS) = name string address
;---------------------------------------
fnm5: mov cx,dx ; (cx) = length to match
pop di
pop es ; (ES:DI) = fba given name
push es
push di
push si ; save MFT offset
add si,mft_name ; (ds:si) = fwa string in record
repz cmpsb
pop si ; (ds:si) = fwa name record
jnz fnm4 ; not a match
;---------------------------------------
; Yes, we've found it. Return the info
;
; (TOS+2:TOS) = name string address
;---------------------------------------
fmt TypShare,LevMFTSrch,<"FNM found name record at $x\n">,<si>
pop ax ; discard unneeded stack stuff
pop ax
mov bx,si ; (ds:bx) = fwa name record
clc
ret
;---------------------------------------
;**
;** Its not in the list
;** - lets find a free spot and put
;** it there
;
; (bh) = create flag
; (bl) = sum byte
; (dx) = string length
; (TOS+2:TOS) = ASCIZ string address
; (ds) = SEG CODE
;---------------------------------------
fnm10:
and bh,bh
jnz fnm10$5 ; yes, insert it
pop si
pop ds ; no insert, its a "not found"
stc
fmt TypShare,LevMFTSrch,<"FNM failing\n">
mov ax,error_path_not_found
ret
fnm10$5:
add dx,mft_name ; (dx) = minimum space needed
off SI,mft
fnm11: cmp [si].mft_flag,MFLG_FRE
IF NOT DEBUG
jl fnm20 ; at END, am out of space
ELSE
jl fnm20j
ENDIF
jz fnm12 ; is a free record
add si,[si].mft_len ; skip name record
JMP SHORT fnm11
IF DEBUG
fnm20j: jmp fnm20
ENDIF
fnm12: mov ax,[si].mft_len ; Have free record, (ax) = total length
cmp ax,dx
jnc fnm13 ; big enough
add si,ax
JMP SHORT fnm11 ; not large enough - move on
;---------------------------------------
; OK, we have a record which is big
; enough. If its large enough to hold
; another name record of 6 characters
; than we'll split the block, else
; we'll just use the whole thing
;
; (ax) = size of free record
; (dx) = size needed
; (ds:si) = address of free record
; (bl) = sum byte
; (TOS+2:TOS) = name string address
;---------------------------------------
fnm13: sub ax,dx ; (ax) = total size of proposed fragment
cmp ax,mft_name+6
jc fnm14 ; not big enough to split
push bx ; save sum byte
mov bx,dx ; (bx) = offset to start of new name record
mov [bx][si].mft_flag,MFLG_FRE
mov [bx][si].mft_len,ax ; setup tail as free record
sub ax,ax ; don't extend this record
pop bx ; restore sum byte
fnm14: add dx,ax ; (dx) = total length of this record
mov [si].mft_len,dx
mov [si].mft_sum,bl
mov [si].mft_flag,MFLG_NAM
fmt TypShare,LevMFTSrch,<"FNM creating record at $x\n">,<si>
push ds
pop es ; (es) = MFT segment for "stow"
sub ax,ax
mov di,si
add di,mft_lptr
stosw ; zero LCK pointer
ERRNZ mft_sptr-mft_lptr-2
; add di,mft_sptr-mft_lptr-2
stosw ; zero SFT pointer
stosw ; zero SFT pointer
inc serial ; bump serial number
mov ax,serial
ERRNZ mft_serl-mft_sptr-4
; ADD di,mft_serl-mft_sptr-4
stosw
;---------------------------------------
; We're all setup except for the name.
; Note that we'll block copy the whole
; name field, even though the name may
; be shorter than that (we may have
; declined to fragment this memory block)
;
; (dx) = total length of this record
; (ds:si) = address of working record
; (es) = (ds)
; (TOS+2:TOS) = name string address
;---------------------------------------
mov cx,dx
sub cx,mft_name ; compute total size of name area
ERRNZ mft_name-mft_serl-2
; add di,mft_name-mft_serl-2 ; (ES:DI) = target address
mov ax,si ; save name record offset
pop si
pop ds
rep movsb
mov bx,ax ; (bx) = name record offset
push es
pop ds ; (DS:BX) = name record offset
clc
ret
;**
;** OUT OF FREE SPACE
;**
;** This is tough, folks. Lets trigger a garbage collection and see if
;** there is enough room. If there is, we'll hop back and relook for a
;** free hunk; if there isnt enough space, its error-city!
;
; WARNING: it is important that the garbage collector be told how big a
; name record hole we're looking for... if the size given GCM
; is too small we'll loop doing "no space; collect; no space;
; ...)
;
; (dx) = total length of desired name record
; (ds) = SEG CODE
; (bl) = sum byte
; (TOS+2:TOS) = name string address
fnm20:
mov ax,dx ; (ax) = size wanted
sub dx,mft_name ; (dx) = string length for reentry at fnm10
push dx
push bx
call GCM ; garbage collect MFT
pop bx
pop dx
IF DEBUG
jnc fnm10j
ELSE
jnc fnm10 ; go back and find that space
ENDIF
;---------------------------------------
; no space, return w/error
;---------------------------------------
fnm50: pop ax
pop ax ; clean stack
mov ax,error_sharing_buffer_exceeded
stc
ret
IF DEBUG
fnm10j: jmp fnm10
ENDIF
EndProc FNM
BREAK <GCM - Garbage Collect MFT>
;******************* START OF SPECIFICATIONS ***********************************
;
; GCM - Garbage Collect MFT
;
; GCM runs down the MFT structure squeezing out the free space and
; putting it into one free block at the end. This is a traditional heap
; collection process. We must be sure to update the pointer in the
; SFTs. This presumes no adjacent free blocks.
;
; ENTRY (ax) = space desired in last free block
; (DS) + SEG CODE
; EXIT 'C' clear if enough space in block
; 'C' set if not enough space
;
;******************* END OF SPECIFICATIONS *************************************
Procedure GCM,NEAR
push ax ; save target
off si,mft ; (si) = from pointer
mov di,si ; (di) = to pointer
;---------------------------------------
; (DI) points to the beginning of
; a free space block
; (SI) points to the next block.
;---------------------------------------
gcm1: mov cx,[si].mft_len ; (cx) = size of whatever it is
cmp [si].mft_flag,MFLG_FRE
jl gcm10 ; END marker
jnz gcm2 ; have a name record
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -