     1                                  ;	Title	Share_1 -  IBM CONFIDENTIAL
     2                                  ;				   $SALUT (0,36,41,44)
     3                                  				   %include "sharehdr.mac"
     1                              <1> ;        page    80,132
     2                              <1> ;******************* START OF SPECIFICATIONS ***********************************
     3                              <1> ;
     4                              <1> ; MODULE NAME:          SHARE.EXE     (a true EXE file)
     5                              <1> ;
     6                              <1> ; DESCRIPTIVE NAME:     SHARE resident service routines - part 1 - GSHARE.SAL
     7                              <1> ;                                                       - part 2 - GSHARE2.SAL
     8                              <1> ;                                                       - part 3 - SHARESR.SAL
     9                              <1> ;
    10                              <1> ; FUNCTION:             Provide file sharing services for DOS
    11                              <1> ;
    12                              <1> ; ENTRY POINT:          DOS Jump Table - installed by SHARE at initalization
    13                              <1> ;
    14                              <1> ;                             MFT_Enter          1
    15                              <1> ;                             MFTClose           2
    16                              <1> ;                             MFTClu             3
    17                              <1> ;                             MFTCloseP          4
    18                              <1> ;                             MFTCloN            5
    19                              <1> ;                             Set_Mult_Block     6
    20                              <1> ;                             Clr_Mult_Block     7
    21                              <1> ;                             Chk_Block          8
    22                              <1> ;                             MFT_Get            9
    23                              <1> ;
    24                              <1> ; INPUT:                See Prolog to individual entry points
    25                              <1> ;
    26                              <1> ; EXIT NORMAL:          CF = 0 and requested task performed.
    27                              <1> ;
    28                              <1> ; EXIT ERROR:           CF = 1 ans error code in AX
    29                              <1> ;
    30                              <1> ; INTERNAL REFERENCES:
    31                              <1> ;
    32                              <1> ;       ROUTINES:       Set_Block               BCS
    33                              <1> ;                       Clr_Block               CSL
    34                              <1> ;                       CLP                     CUC
    35                              <1> ;                       Load_Regs               CSI
    36                              <1> ;                       ASC                     GOM
    37                              <1> ;
    38                              <1> ;       DATA AREAS:
    39                              <1> ;
    40                              <1> ; EXTERNAL REFERENCES:  INT 21       INT 2F
    41                              <1> ;     together with:
    42                              <1> ;
    43                              <1> ;     fnm:near, rsc:near, rmn:near, cps:near, ofl:near, sle:near, interr:near
    44                              <1> ;
    45                              <1> ;       ROUTINES:
    46                              <1> ;
    47                              <1> ;       DATA AREAS:
    48                              <1> ;
    49                              <1> ; NOTES:                The second part of this utility is GSHARE2.ASM
    50                              <1> ;
    51                              <1> ; REVISION HISTORY:       Version 1.0  09/09/83 - first release              GL
    52                              <1> ;                                      09/13/83 - Installability             MZ
    53                              <1> ;                                      01/11/84 - FCB compatability changes  MZ
    54                              <1> ;                         PTM P000438  08/21/86 - SFT LCK FIELDS not 0 error DL
    55                              <1> ;                   Ax000 Ver 4.0      04/15/87 - changed:- Set_Block        FJG
    56                              <1> ;                                                         - Clr_Block        FJG
    57                              <1> ;                                                         - Chk_Block        FJG
    58                              <1> ;                                                         - CLP              FJG
    59                              <1> ;                                                  new:   - Set_Mult_Block   FJG
    60                              <1> ;                                                         - Clr_Mult_Block   FJG
    61                              <1> ;                                                         - Load_Regs        FJG
    62                              <1> ;                                                         - Clr_List         FJG
    63                              <1> ;                   Ax002  PTM P001658  10/15/87 - changed I/F to IBMDOS     FJG
    64                              <1> ;                   Ax003  PTM P002064  10/15/87 - ShSU SFT - IFS call error FJG
    65                              <1> ;                   Ax004  PTM P002121  10/29/87 - Clr_Mult_Block cx=-1 err  FJG
    66                              <1> ;                   Ax005  PTM P002322  11/06/87 - Call_IFS - 2F semaphore   FJG
    67                              <1> ;                   Ax006  DCR D000494  12/17/87 - DOS 4.00 function reductionFJG
    68                              <1> ;                   Ax007  PTM P003841  03/17/88 - access error for Turbo L  FJG
    69                              <1> ;                   Ax008  PTM P003880  03/17/88 - duped handle error        FJG
    70                              <1> ;                   Ax009  PTM P003910  03/17/88 - wrong parse error format  FJG
    71                              <1> ;                   Ax010  DCR D000526  04/27/88 - add /nc switch support    FJG
    72                              <1> ;                   Ax011  PTM P004546  05/03/88 - add /nc support to fShare FJG
     4                                  ;
     5                                  ;     Label: "The DOS SHARE Utility"
     6                                  ;	     "Version 4.00 (C) Copyright 1988 Microsoft"
     7                                  ;	     "Licenced Material - Program Property of Microsoft"
     8                                  ;
     9                                  ;******************* END OF SPECIFICATIONS *************************************
    10                                  
    11                                  section SHARE align=16 PUBLIC class=SHARE
    12                                  extrn				   fnm:near, rsc:near, rmn:near, cps:near, ofl:near, sle:near, interr:near
    13                                  
    14                                  ;				   NAME Sharer
    15                                  
    16                                  				   [list -]
    16          ******************       warning: out: ... for DOS Version 4.00 ... [-w+user]
    16          ******************       warning: out: BPB.INC... [-w+user]
    16          ******************       warning: out: ... CLONE version build switch on ... [-w+user]
    24                                  
    25                                  %ifndef IBM
    26                                   %iassign IBM 0
    27                                  %endif
    28                                  %ifndef Installed
    29                                   %iassign Installed 0
    30                                  %endif
    31                                  
    32                                  %iassign Installed	TRUE ; for installed version
    33                                  
    34                                  ; NASM original macros
    35                                  
    36                                  %imacro OFF 2.nolist
    37                                   %if Installed
    38                                  	mov %1, offset %2
    39                                   %else
    40                                  	mov %1, offset %2 wrt DOSGROUP
    41                                   %endif
    42                                  %endmacro
    43                                  
    44                                  %unimacro detectstripangles 4.nolist
    45                                  
    46                                  %imacro detectstripangles 4.nolist
    47                                  %defstr %%param %4
    48                                  %assign ?%2 0
    49                                  %assign ?%3 0
    50                                  %rep 16
    51                                   %substr %%opening %%param 1
    52                                   %ifidn %%opening, '<'
    53                                    %substr %%param %%param 2,-1
    54                                    %assign ?%2 ?%2 + 1
    55                                   %endif
    56                                  %endrep
    57                                  %rep 16
    58                                   %strlen %%length %%param
    59                                   %substr %%closing %%param %%length
    60                                   %ifidn %%closing, '>'
    61                                    %substr %%param %%param 1,-2
    62                                    %assign ?%3 ?%3 + 1
    63                                   %endif
    64                                  %endrep
    65                                  %deftok %%token %%param
    66                                  %define ?%1 %%token
    67                                  %endmacro
    68                                  
    69                                  %unimacro errnz 1.nolist
    70                                  
    71                                  %imacro errnz 1.nolist
    72                                  detectstripangles %%token, %%opening, %%closing, %1
    73                                  %if ? %+ %%token
    74                                      %error %1 <> 0, ERRNZ failed
    75                                  %endif
    76                                  %endmacro
    77                                  
    78                                  ; end of NASM original macros
    79                                  
    80                                  mft equ MFT	; NASM port label
    81                                  quux equ mft
    82                                  
    83                                  ; if we are installed, then define the base code segment of the sharer first
    84                                  
    85                                  				   %IF	Installed
    86                                  section SHARE
    87                                  ; (no prior section) ; Share				   ENDS
    88                                  ; include the rest of the segment definitions for normal msdos
    89                                  ; We CANNOT include dosseg because start is not declared para in that file
    90                                  
    91                                  section WLEMITALIGNED align=16
    92                                  ;	$SALUT	(4,9,17,36)
    93                                  
    94                                  section DOSSTART align=16 PUBLIC class=DOSSTART
    95                                  ; (no prior section) ; DOSSTART	ENDS
    96                                  
    97                                  section START align=1 PUBLIC class=START
    98                                  ; (no prior section) ; START	ENDS
    99                                  
   100                                  section CONSTANTS align=2 PUBLIC class=CONST
   101                                  ; (no prior section) ; CONSTANTS ENDS
   102                                  
   103                                  section DATA align=2 PUBLIC class=DATA
   104                                  ; (no prior section) ; DATA	ENDS
   105                                  
   106                                  section TABLE align=1 PUBLIC class=TABLE
   107                                  ; (no prior section) ; TABLE	ENDS
   108                                  
   109                                  section CODE align=1 PUBLIC class=CODE
   110                                  ; (no prior section) ; CODE	ENDS
   111                                  
   112                                  section LAST align=16 PUBLIC class=LAST
   113                                  ; (no prior section) ; LAST	ENDS
   114                                  
   115                                  group DOSGROUP DOSSTART START CONSTANTS DATA TABLE CODE LAST
   116                                  	%ELSE
   117                                  	%include "dosseg.nas"
   118                                  	%ENDIF
   119                                  
   120                                  section STACK stack class=STACK
   121                                  ; (no prior section) ; STACK	ENDS
   122                                  
   123                                  section DATA
   124                                  	Extrn	ThisSFT:DWORD	   ; pointer to SFT entry
   125                                  	Extrn	User_ID:WORD
   126                                  	Extrn	Proc_ID:WORD
   127                                  	Extrn	WFP_START:WORD
   128                                  	Extrn	BytPos:DWORD
   129                                  	extrn	OpenBuf:BYTE
   130                                  	extrn	user_in_ax:WORD
   131                                  	%IF	debug
   132                                  	    Extrn   BugLev:WORD
   133                                  	    Extrn   BugTyp:WORD
   134                                  	    %include "bugtyp.nas"
   135                                  	%ENDIF
   136                                  ; (no prior section) ; DATA	ENDS
   137                                  
   138                                  ;   if we are not installed, then the code here is just part of the normal
   139                                  ;   MSDOS code segment otherwise, define our own code segment
   140                                  
   141                                  ;	.sall
   142                                  	%IFN INSTALLED
   143                                  section CODE
   144                                  	    ASSUME  SS:DOSGROUP,CS:DOSGROUP
   145                                  	%ELSE
   146                                  section SHARE
   147                                  	    ASSUME  SS:DOSGROUP,CS:SHARE
   148                                  	%ENDIF
   149                                  
   150                                  	extrn	MFT:BYTE
   151                                  	extrn	skip_check:BYTE
   152                                  
   153                                  	%include "mft.mac"
     1                              <1> BREAK   <MFT Definitions>
     2                              <1> 
     3                              <1> ;**     MSDOS MFT definitions
     4                              <1> ;
     5                              <1> ;   The Master File Table (MFT) associates the cannonicalized pathnames, lock
     6                              <1> ;   records and SFTs for all files open on this machine.
     7                              <1> ;
     8                              <1> ;   The MFT implementation employs a single memory buffer which is used from
     9                              <1> ;   both ends.  This gives the effect (at least until they run into each
    10                              <1> ;   other) of two independent buffers.
    11                              <1> ;
    12                              <1> ;       MFT buffer
    13                              <1> ;       ==========
    14                              <1> ;   The MFT buffer contains MFT name records and free space.  It uses a
    15                              <1> ;   classic heap architecture:  freed name records are marked free and
    16                              <1> ;   conglomerated with any adjacent free space.  When one is to create a name
    17                              <1> ;   entry the free list is searched first-fit.  The list of name and free
    18                              <1> ;   records is always terminated by a single END record.
    19                              <1> ;
    20                              <1> ;       LOCK buffer
    21                              <1> ;       ===========
    22                              <1> ;   The lock buffer contains fixed format records containing record locking
    23                              <1> ;   information.  Since they are fixed format the space is handled as a series
    24                              <1> ;   of chains:  one for each MFT name record and one for the free list.  No
    25                              <1> ;   garbage collection is necessary.
    26                              <1> ;
    27                              <1> ;       Space allocation
    28                              <1> ;       ================
    29                              <1> ;   The MFT is managed as a heap.  Empty blocks are allocated on a first-fit
    30                              <1> ;   basis.  If there is no single large enough empty block the list is garbage
    31                              <1> ;   collected.
    32                              <1> ;
    33                              <1> ;       MFT name records:
    34                              <1> ;
    35                              <1> ;              8     16     8     16     32     16        n
    36                              <1> ;           |------|-----|-----|------|------|------|---------~~~~~~---------|
    37                              <1> ;           | FLAG | LEN | SUM | LPTR | SPTR | SERL |     <.asciz string>    |
    38                              <1> ;           --------------------------------------------------~~~~~~----------
    39                              <1> ;
    40                              <1> ;                       FLAG = record type flag
    41                              <1> ;                       LEN =  total byte length of record.
    42                              <1> ;                       SUM =  sum of bytes in asciz string.  Used to speed
    43                              <1> ;                              searches
    44                              <1> ;                       LPTR=  pointer to first record in lock chain segment
    45                              <1> ;                              is MFT segment
    46                              <1> ;                       SPTR= pointer to first sft in sft chain
    47                              <1> ;                       SERL= serial number
    48                              <1> ;                       <string> = name string, zero-byte terminated.  There
    49                              <1> ;                              may be garbage bytes following the 00 byte;
    50                              <1> ;                              these are counted in the LEN field.
    51                              <1> ;
    52                              <1> ;
    53                              <1> ;       MFT free records
    54                              <1> ;
    55                              <1> ;              8      16
    56                              <1> ;           |------|-----|----~~~~~~~~~~~~~~~~~~~~~~~~~~~---------|
    57                              <1> ;           | FLAG | LEN |         free                           |
    58                              <1> ;           ------------------~~~~~~~~~~~~~~~~~~~~~~~~~~~----------
    59                              <1> ;
    60                              <1> ;                       FLAG = record type flag
    61                              <1> ;                       LEN  = total byte length of record.
    62                              <1> ;
    63                              <1> ;
    64                              <1> ;       MFT END records
    65                              <1> ;
    66                              <1> ;                  8
    67                              <1> ;               |------|
    68                              <1> ;               | FLAG |
    69                              <1> ;               --------
    70                              <1> ;
    71                              <1> ;                       FLAG = record type flag
    72                              <1> 
    73                              <1> ;**     MFT definitions
    74                              <1> ;*
    75                              <1> ;*      NOTE:  the flag and length fields are identical for all record types
    76                              <1> ;*              (except the END type has no length) This must remain so as
    77                              <1> ;*              some code depends upon it.
    78                              <1> ;*
    79                              <1> ;*      NOTE:  Many routines check for "n-1" of the N flag values and if no
    80                              <1> ;*              match is found assume the flag value must be the remaining
    81                              <1> ;*              possibility.  If you add or remove flag values you must check
    82                              <1> ;*              all references to mft_flag.
    83                              <1> 
    84                              <1> MFT_entry       STRUC
    85                              <1> 
    86 00000000 ??                  <1> mft_flag        DB      ?               ; flag/len field
    87 00000001 ????                <1> mft_len         DW      ?
    88 00000003 ??                  <1> mft_sum         DB      ?               ; string sum word
    89 00000004 ????                <1> mft_lptr        DW      ?               ; LCK pointer
    90 00000006 ????????            <1> mft_sptr        DD      ?               ; sft pointer
    91 0000000A ????                <1> mft_serl        DW      ?               ; serial number
    92 0000000C ??                  <1> mft_name        DB      ?               ; offset to start of name
    93                              <1> 
    94                              <1> MFT_entry       ENDS
    95                              <1> 
    96                              <1> MFLG_NAM        EQU     1               ; min value for name record
    97                              <1> MFLG_FRE        EQU     0               ; free record
    98                              <1> MFLG_END        EQU     -1              ; end record
    99                              <1> 
   100                              <1> ;*      Record Lock Record (RLR):
   101                              <1> ;
   102                              <1> ;                  16       32       32       32
   103                              <1> ;               |-------|--------|--------|--------|
   104                              <1> ;               | NEXT  |  FBA   |  LBA   |  SPTR  |
   105                              <1> ;               |       | lo hi  | lo hi  |        |
   106                              <1> ;               ------------|--------|--------------
   107                              <1> ;
   108                              <1> ;                       CHAIN  = pointer to next RLR.  0 if end
   109                              <1> ;                       FBA    = offset of 1st  byte of locked region
   110                              <1> ;                       LBA    = offset of last byte of locked region
   111                              <1> ;                       SPTR   = pointer to SFT lock was issued on
   112                              <1> 
   113                              <1> RLR_entry       STRUC
   114                              <1> 
   115 00000000 ????                <1> rlr_next        DW      ?               ; chain to next RLR, 0 if end
   116 00000002 ????                <1> rlr_fba         DW      ?               ; first byte addr (offset) of reigion
   117 00000004 ????                <1>                 DW      ?
   118 00000006 ????                <1> rlr_lba         DW      ?               ; last byte addr of region
   119 00000008 ????                <1>                 DW      ?
   120 0000000A ????????            <1> rlr_sptr        DD      ?               ; SFT pointer
   121 0000000E ????                <1> rlr_pid         dw      ?               ; process id of issuer
   122 00000010 ????                <1> rlr_type        dw      ?               ; lock type
   123                              <1> RLR_entry       ENDS
   124                              <1> 
   125                              <1> rlr_lall        equ     00h            ; lock all ops
   126                              <1> rlr_lwr         equ     01h            ; lock write ops
   127                              <1> 
   128                              <1> ;
   129                              <1> ;   A pictorial diagram for the linkages is as follows:
   130                              <1> ;
   131                              <1> ;          +---sptr------+
   132                              <1> ;          V             |
   133                              <1> ;        +---+<----------|---sptr------+------------+
   134                              <1> ;        |SFT+----+      |             |            |
   135                              <1> ;        +-+-+    |    +-+-+        +--+-+       +--+-+
   136                              <1> ;          V      +--->|MFT+-lptr->-|LOCK+-next->|LOCK+->0
   137                              <1> ;        +---+    |    +---+        +----+       +----+
   138                              <1> ;        |SFT+----+      ^
   139                              <1> ;        +-+-+           |
   140                              <1> ;          |             |
   141                              <1> ;          +-------------+
   142                              <1> ;
   143                              <1> ;
   144                              <1> 
   145                              <1> ;**
   146                              <1> ;
   147                              <1> ;   Interesting behavior should be noted:
   148                              <1> ;
   149                              <1> ;       The sharer must maintain information on files in three forms:
   150                              <1> ;
   151                              <1> ;       local/remote handles.  These are normal handles and behave in no
   152                              <1> ;           strange manner.  They are identified by SF_mode not having the
   153                              <1> ;           sfIsFCB flag nor by having the sf_mode = 70.  No problems with
   154                              <1> ;           locking.  No problems with open.  No problems with close.
   155                              <1> ;           CloseByName will iterate closes until the mft disappears.
   156                              <1> ;           CloseUser will iterate closes until no SFT for the particular user
   157                              <1> ;           appears.  CloseProcess will iterate closes until no SFT for the
   158                              <1> ;           particular user/process appears.
   159                              <1> ;
   160                              <1> ;       local FCBs.  There are no corresponding SFT's for these as the SFTs
   161                              <1> ;           are cached but will be valid for the particular file.  There is
   162                              <1> ;           one SFT for each open on a file by a specific process.  These are
   163                              <1> ;           identified the sfIsFCB flag in the sf_mode field.  When multiple
   164                              <1> ;           opens occur, we merely find the sf pertinent to the file and
   165                              <1> ;           process.  Close decrements the ref count.  CloseByName, CloseUser,
   166                              <1> ;           CloseProcess will iterate closes until no more SFTs exist.
   167                              <1> ;
   168                              <1> ;       handles with mode 70.  These represent FCB's open across the network.
   169                              <1> ;           As such, identical sfts may have been collapsed by the $open code.
   170                              <1> ;           This results in a reuse of the same SFT.  The $Open code must
   171                              <1> ;           correctly set the ref-count for the sft to reflect the number of
   172                              <1> ;           collapses that have occurred.  These are identified by a 70 in the
   173                              <1> ;           SF_mode field.  There can be no locking on these SFTs.  Open must
   174                              <1> ;           scan the list of SFTs for the file and increment its ref count
   175                              <1> ;           appropriately.
   154                                  
   155                                  FreLock equ Frelock	; NASM port label
   156                                  	PUBLIC	FreLock,Serial
   157                                  
   158                                  	%IF	installed
   159 00000000 ????                    Frelock     DW	    ?		   ; FWA of lock free list
   160                                  	%ELSE
   161                                  Frelock     DW	    OFFSET lck8 wrt DOSGROUP ; FWA of lock free list
   162                                  	%ENDIF
   163 00000002 0000                    Serial	DW	0		   ; serial number
   164 00000004 0000                    DS_Org	dw	0		   ;an000;DS on entry to routine
   165                                  
   166                                  ZERO	EQU	0
   167                                  ONE	EQU	1
   168                                  
   169                                  FRAME	struc
   170                                  
   171 00000000 ????                    SavedBP dw	?
   172 00000002 ????                    RetOFF	dw	?
   173 00000004 ????                    Parm_1	dw	?
   174 00000006 ????                    Parm_2	dw	?
   175                                  
   176                                  FRAME	ends
   177                                  
   178                                  ;  $SALUT (4,4,9,41)
   179                                  
   180                                     BREAK <Sharer - MultiProcess File Sharer>
   181                                  
   182                                  ;******************* START OF SPECIFICATIONS ***********************************
   183                                  ;
   184                                  ;	MSDOS MFT Functions
   185                                  ;
   186                                  ;	The Master File Table (MFT) associates the cannonicalized pathnames,
   187                                  ;	lock records and SFTs for all files open on this machine.
   188                                  ;
   189                                  ;	These functions are supplied to maintain the MFT and extract
   190                                  ;	information from it.  All MFT access should be via these routines so
   191                                  ;	that the MFT structure can remain flexible.
   192                                  ;
   193                                  ;******************* END OF SPECIFICATIONS *************************************
   194                                  
   195                                     BREAK <Mft_enter - Make an MFT entry and check access>
   196                                  
   197                                  ;******************* START OF SPECIFICATIONS ***********************************
   198                                  ;
   199                                  ;	mft_enter - make an entry in the MFT
   200                                  ;
   201                                  ;	mft_enter is called to make an entry in the MFT.
   202                                  ;	mft_enter checks for a file sharing conflict:
   203                                  ;		No conflict:
   204                                  ;		    A new MFT entry is created, or the existing one updated,
   205                                  ;		    as appropriate.
   206                                  ;		Conflicts:
   207                                  ;		    The existing MFT is left alone.  Note that if we had to
   208                                  ;		    create a new MFT there cannot be, by definition, sharing
   209                                  ;		    conflicts.
   210                                  ;	If no conflict has been discovered, the SFT list for the file is
   211                                  ;	checked for one that matches the following conditions:
   212                                  ;
   213                                  ;	    If mode == 70 then
   214                                  ;		don't link in SFT
   215                                  ;		increment refcount
   216                                  ;	    If mode&sfIsFCB and userids match and process ids match then
   217                                  ;		don't link in SFT
   218                                  ;
   219                                  ;	ENTRY	ThisSFT points to an SFT structure.  The sf_mode field
   220                                  ;		    contains the desired sharing mode.
   221                                  ;		WFP_Start is an offset from DOSGroup of the full pathname for
   222                                  ;		    the file
   223                                  ;		User_ID = 16-bit user id of issuer
   224                                  ;		Proc_ID = 16-bit process id of issuer
   225                                  ;		(DS) = (SS) = DOSGroup
   226                                  ;	EXIT	'C' clear if no error'
   227                                  ;		'C' set if error
   228                                  ;		  (ax) = error code
   229                                  ;	USES	ALL but DS
   230                                  ;
   231                                  ;******************* END OF SPECIFICATIONS *************************************
   232                                  
   233                                     Procedure mft_enter,NEAR
   233          ******************       warning: proc mft_enter... [-w+user]
   234                                  
   235                                  ;  int 3
   236 00000006 90                         nop
   237 00000007 90                         nop
   238                                  
   239 00000008 E8(0000)                   EnterCrit critShare
   240                                  
   241                                     DOSAssume SS, <DS>, "MFT_Enter entry"
   242                                     ASSUME ES:NOTHING,SS:DOSGROUP
   243 0000000B 1E                         push ds
   244                                  
   245                                  ;	find or make a name record
   246                                  
   247                                  WFP_Start equ WFP_START	; NASM port label
   248 0000000C 8B36[0000]                 mov	si,[WFP_Start]			; (DS:SI) = FBA of file name
   249 00000010 B001                       mov	al,1				; allow creation of MFT entry
   250 00000012 06                         push es
   251                                  
   252                                     ASSUME DS:NOTHING
   253                                  
   254                                  FNM equ fnm	; NASM port label
   255 00000013 E8(0000)                   call FNM				; find or create name in MFT
   256 00000016 07                         pop	es
   257 00000017 B82400                     mov	ax,error_sharing_buffer_exceeded
   258 0000001A 7208                       jc	ent9				; not enough space
   259                                  ;
   260                                  ;	(bx) = fwa name record
   261                                  ;
   262 0000001C 36C536[0000]               lds	si,[ss:ThisSFT]
   263 00000021 E88702                     call ASC				; try to add to chain
   264                                  
   265                                  ;	As noted above, we don't have to worry about an "empty" name record
   266                                  ;	being left if ASC refuses to add the SFT - ASC cannot refuse if we had
   267                                  ;	just created the MFT...
   268                                  
   269                                  ;	return.
   270                                  ;
   271                                  ;	'C' and (Ax) setup appropriately
   272                                  
   273 00000024 1F                      ent9: pop ds
   274                                  
   275 00000025 E8(0000)                   LeaveCrit critShare
   276                                  
   277 00000028 C3                         ret
   278                                  
   279                                     EndProc mft_enter
   280                                  
   281                                     BREAK <MftClose - Close out an MFT for given SFT>
   282                                  
   283                                  ;******************* START OF SPECIFICATIONS ***********************************
   284                                  ;
   285                                  ;	MFTclose
   286                                  ;
   287                                  ;	MFTclose(SFT)
   288                                  ;
   289                                  ;	MFTclose removes the SFT entry from the MFT structure.	If this was
   290                                  ;	the last SFT for the particular file the file's entry is also removed
   291                                  ;	from the MFT structure.  If the sharer is installed after some
   292                                  ;	processing has been done, the MFT field of the SFTs will be 0; we must
   293                                  ;	ignore these guys.
   294                                  ;
   295                                  ;	If the sft indicates FCB, we do nothing special.  The SFT behaves
   296                                  ;	    EXACTLY like a normal handle.
   297                                  ;
   298                                  ;	If the sft indicates mode 70 then we do nothing special.  These are
   299                                  ;	normal HANDLES.
   300                                  ;
   301                                  ;	Note that we always care about the SFT refcount.  A refcount of 1
   302                                  ;	means that the SFT is going idle and that we need to remove the sft
   303                                  ;	from the chain.
   304                                  ;
   305                                  ;	ENTRY	(ES:DI) points to an SFT structure
   306                                  ;		(DS) = (SS) = DOSGroup
   307                                  ;	EXIT	NONE
   308                                  ;	USES	ALL but DS, ES:DI
   309                                  ;
   310                                  ;******************* END OF SPECIFICATIONS *************************************
   311                                  
   312                                     Procedure MFTclose,NEAR
   312          ******************       warning: proc MFTclose... [-w+user]
   313                                  
   314                                  ;  int 3
   315 00000029 90                         nop
   316 0000002A 90                         nop
   317                                  
   318 0000002B E8(0000)                   EnterCrit critShare
   319                                  
   320                                     DOSAssume SS,<DS>,"MFTClose entry"
   321                                     ASSUME ES:NOTHING
   322 0000002E 268B4533                   mov	ax,[es:di + sf_MFT]
   323                                  
   324                                     fmt	TypShare,LevShEntry,<"MFTClose by $x:$x of $x:$x ($x)\n">,<User_ID,Proc_id,ES,DI,AX>
   325                                  
   326 00000032 09C0                       or	ax,ax
   327 00000034 741B                       jz	mcl10				; No entry for it, ignore (carry clear)
   328 00000036 1E                         push ds
   329 00000037 06                         push es
   330 00000038 57                         push di
   331                                  ;;;call CSL				; clear SFT locks		       ;AC008;
   332                                  
   333                                     ASSUME DS:NOTHING
   334                                  
   335 00000039 268B05                     mov	ax,[es:di + sf_ref_count] 	; (ax) = ref count
   336                                  ;
   337                                  ; We need to release information in one of two spots.  First, when the SFT has
   338                                  ; a ref count of 0.  Here, there are no more referents and, thus, no sharing
   339                                  ; record need be kept.	Second, the ref count may be -1 indicating that the
   340                                  ; sft is being kept but that the sharing information is no longer needed.
   341                                  ; This occurs in creates of existing files, where we verify the allowed
   342                                  ; access, truncate the file and regain the access.  If the truncation
   343                                  ; generates an error, we do NOT want to have the access locked down.
   344                                  ;
   345                                  
   346                                  
   347 0000003C 09C0                       OR	AX,AX
   348 0000003E 7403                       jz	mcl85				; ref count is 0 - don't dechain
   349 00000040 40                         inc	ax				; -1 + 1 = 0.  Busy sft.
   350 00000041 750B                       jnz	mcl9
   351                                  mcl85:
   352 00000043 E84203                     call CSL				; clear SFT locks		       ;AC008;
   353                                  RSC equ rsc	; NASM port label
   354 00000046 E8(0000)                   call RSC				; remove sft from chain
   355 00000049 7503                       jnz	mcl9				; not the last sft for this name
   356                                  RMN equ rmn	; NASM port label
   357 0000004B E8(0000)                   call RMN				; remove name record
   358                                  mcl9:
   359 0000004E 5F                         pop	di				; restore regs for exit
   360 0000004F 07                         pop	es
   361 00000050 1F                         pop	ds
   362                                  mcl10:
   363 00000051 E8(0000)                   LeaveCrit critShare
   364                                  
   365 00000054 C3                         ret
   366                                  
   367                                     EndProc MFTclose
   368                                  
   369                                     BREAK <MftClU - Close out all MFTs for given UID>
   370                                  
   371                                  ;******************* START OF SPECIFICATIONS ***********************************
   372                                  ;
   373                                  ;	MFTcloseU
   374                                  ;
   375                                  ;	MFTcloseM(UID)
   376                                  ;
   377                                  ;	MFTcloseM removes all entrys for user UID from the MFT structure.  We
   378                                  ;	    walk the MFT structure closing all relevant SFT's for the user.
   379                                  ;	    We do it the dumb way, iterating closes until the SF ref count is
   380                                  ;	    0.
   381                                  ;
   382                                  ;	ENTRY	User_ID = 16-bit user id of issuer
   383                                  ;		(SS) + DOSGroup
   384                                  ;	EXIT	'C' clear
   385                                  ;	USES	ALL
   386                                  ;
   387                                  ;******************* END OF SPECIFICATIONS *************************************
   388                                  
   389                                     Procedure MFTclU,NEAR
   389          ******************       warning: proc MFTclU... [-w+user]
   390                                  
   391                                  ;  int 3
   392 00000055 90                         nop
   393 00000056 90                         nop
   394                                  
   395                                     ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP
   396                                  
   397 00000057 E8(0000)                   EnterCrit critShare
   398 0000005A 36A1[0000]                 mov	ax,[ss:User_ID]
   399                                  
   400                                     fmt	TypShare,LevShEntry,<"\nCloseUser $x\n">,<AX>
   401                                  
   402 0000005E 29DB                       sub	bx,bx				; insensitive to PID
   403 00000060 29D2                       sub	dx,dx
   404 00000062 E8A702                     invoke BCS				; bulk close the SFTs
   405 00000065 E8(0000)                   LeaveCrit critShare
   406 00000068 C3                         return
   407                                     EndProc MFTclU
   408                                  
   409                                     BREAK <MftCloseP - Close out all MFTs for given UID/PID>
   410                                  
   411                                  ;******************* START OF SPECIFICATIONS ***********************************
   412                                  ;
   413                                  ;	MFTcloseP
   414                                  ;
   415                                  ;	MFTcloseP(PID, UID)
   416                                  ;
   417                                  ;	MFTcloseP removes all entrys for process PID on machine MID from the
   418                                  ;	    MFT structure.  We walk the MFT structure closing all relevant
   419                                  ;	    SFT's.  Do it the dumb way by iterating closes until the SFTs
   420                                  ;	    disappear.
   421                                  ;
   422                                  ;	ENTRY	(SS) = DOSGROUP
   423                                  ;		User_ID = 16-bit user id of issuer
   424                                  ;		Proc_ID = 16-bit process id of issuer
   425                                  ;	EXIT	'C' clear
   426                                  ;	USES	ALL
   427                                  ;
   428                                  ;******************* END OF SPECIFICATIONS *************************************
   429                                  
   430                                     Procedure MFTcloseP,NEAR
   430          ******************       warning: proc MFTcloseP... [-w+user]
   431                                  
   432                                  ;  int 3
   433 00000069 90                         nop
   434 0000006A 90                         nop
   435                                  
   436                                     ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP
   437                                  
   438 0000006B E8(0000)                   EnterCrit critShare
   439 0000006E 36A1[0000]                 mov	ax,[ss:User_ID]
   440 00000072 BBFFFF                     mov	bx,-1
   441 00000075 368B16[0000]               mov	dx,[ss:Proc_ID]
   442                                  
   443                                     fmt	TypShare,LevShEntry,<"\nClose UID/PID $x:$x\n">,<AX,DX>
   444                                  
   445 0000007A E88F02                     call BCS				; Bulk close the SFTs
   446 0000007D E8(0000)                   LeaveCrit critShare
   447                                  
   448 00000080 C3                         ret
   449                                  
   450                                     EndProc MFTcloseP
   451                                  
   452                                     BREAK <MftCloN - Close file by name>
   453                                  
   454                                  ;******************* START OF SPECIFICATIONS ***********************************
   455                                  ;
   456                                  ;	MFTcloseN
   457                                  ;
   458                                  ;	MFTcloseN(name)
   459                                  ;
   460                                  ;	MFTcloseN removes all entrys for the given file from the MFT
   461                                  ;	structure.
   462                                  ;
   463                                  ;	NOTE: this function is used infrequently and need not be fast.
   464                                  ;		(although for typical use it's not all that slow...)
   465                                  ;
   466                                  ;	ENTRY	DS:SI point to dpl.
   467                                  ;		(SS) = DOSGroup
   468                                  ;	EXIT	'C' clear if no error
   469                                  ;		'C' set if error
   470                                  ;		  AX = error_path_not_found if not currently open
   471                                  ;	USES	ALL
   472                                  ;
   473                                  ;******************* END OF SPECIFICATIONS *************************************
   474                                  
   475                                     Procedure MFTcloN,NEAR
   475          ******************       warning: proc MFTcloN... [-w+user]
   476                                  
   477                                  ;  int 3
   478 00000081 90                         nop
   479 00000082 90                         nop
   480                                  
   481                                     ASSUME SS:DOSGROUP,ES:NOTHING,DS:NOTHING
   482                                  
   483 00000083 E8(0000)                   EnterCrit critShare
   484 00000086 8B5406                     MOV	DX,[SI + DPL_DX]
   485 00000089 8E5C0C                     MOV	DS,[SI + DPL_DS]
   486 0000008C 89D6                       mov	si,dx				; (DS:SI) = fwa name
   487 0000008E 28C0                       sub	al,al				; don't create if not found
   488 00000090 1E                         push ds
   489 00000091 56                         push si
   490 00000092 E8(0000)                   call FNM				; find name in MFT
   491 00000095 B80300                     mov	ax,error_path_not_found 	; assume error
   492 00000098 7229                       jc	mclo9				; not found exit
   493                                  
   494                                  ;	Name was found.  Lets yank the SFT entrys one at a time.
   495                                  
   496 0000009A C47F06                  mclo1: les di,[bx + mft_sptr]		; (ES:DI) = SFT address
   497 0000009D 36893E[0000]               mov	WORD PTR [ss:ThisSFT],di
   498 000000A2 368C06[0200]               mov	WORD PTR [ss:ThisSFT+2],es		; point to SFT
   499 000000A7 26833D01                   cmp	word [es:di + sf_ref_count],1
   500 000000AB 7503                       jnz	mclo15
   501                                  CPS equ cps	; NASM port label
   502 000000AD E8(0000)                   call CPS
   503                                  mclo15:
   504 000000B0 161F                       Context DS
   505                                  
   506                                     %IF	installed
   507                                  multDOS equ MultDOS	; NASM port equate
   508 000000B2 B80112                         MOV  AX,(multDOS << 8) + 1
   509 000000B5 CD2F                           INT  2FH
   510                                     %ELSE
   511                                         call DOS_Close
   512                                     %ENDIF
   513                                  mclo2:
   514                                  
   515                                     ASSUME DS:NOTHING
   516                                  
   517 000000B7 5E                         pop	si
   518 000000B8 1F                         pop	ds
   519 000000B9 1E                         push ds
   520 000000BA 56                         push si
   521 000000BB 28C0                       sub	al,al				; don't create an entry
   522 000000BD E8(0000)                   call FNM				; find the name gain
   523 000000C0 73D8                       jnc	mclo1				; got still more
   524 000000C2 F8                         clc
   525                                  
   526                                  ;	exit.  'C' and (ax) setup
   527                                  ;
   528                                  ;	(TOS+2:TOS) = address of ASCIZ string
   529                                  
   530 000000C3 5E                      mclo9: pop si				; clean stack
   531 000000C4 1F                         pop	ds
   532 000000C5 E8(0000)                   LeaveCrit critShare
   533                                  
   534 000000C8 C3                         ret
   535                                  
   536                                     EndProc MFTcloN
   537                                  
   538                                     BREAK <Set_Mult_Block - Try to set multiple locks>
   539                                  
   540                                  ;******************* START OF SPECIFICATIONS ***********************************
   541                                  ;
   542                                  ;  NAME:	   Set_Mult_Block  -  Set Multiple Block Locks
   543                                  ;
   544                                  ;  FUNCTION:	   Set_Mult_Block sets a lock on 1 or more specified ranges
   545                                  ;		   of a file.  An error is returned if any lock range conflicts
   546                                  ;		   with another. Ranges of Locks are cleared via Clr_Mult_Block.
   547                                  ;
   548                                  ;		   In DOS 3.3 only one lock range could be set at a time using
   549                                  ;		   Set_Block.  For DOS 4.00 this routine will replace Set_Block
   550                                  ;		   in the jump table and will make repeated calls to Set_Block
   551                                  ;		   in order to process 1 or more lock ranges.
   552                                  ;
   553                                  ;		   NOTE: - This is an all new interface to IBMDOS
   554                                  ;
   555                                  ;  INPUT:	   (AL) = 0  - lock all
   556                                  ;			= 80 - lock write
   557                                  ;		   (CX) = the number of lock ranges
   558                                  ;		   (DS:DX) = pointer to the range list
   559                                  ;		   (ES:DI) = SFT address
   560                                  ;		   User_ID = 16-bit user id of issuer
   561                                  ;		   Proc_ID = 16-bit process id of issuer
   562                                  ;		   (SS) = DOSGroup
   563                                  ;
   564                                  ;  OUTPUT:	   Lock records filled in for all blocks specified
   565                                  ;
   566                                  ;  REGISTERS USED: ALL but DS
   567                                  ;  (NOT RESTORED)
   568                                  ;
   569                                  ;  LINKAGE:	   IBMDOS Jump Table
   570                                  ;
   571                                  ;  EXTERNAL	   Invoke: Load_Regs, Set_Block, Clr_Block
   572                                  ;  REFERENCES:
   573                                  ;
   574                                  ;  NORMAL	   'C' clear if no error
   575                                  ;  EXIT:
   576                                  ;
   577                                  ;  ERROR	   'C' set if error
   578                                  ;  EXIT:	     (ax) = error code
   579                                  ;			       ('error_lock_violation' if conflicting locks)
   580                                  ;
   581                                  ;  CHANGE	04/15/87 - First release
   582                                  ;  LOG:
   583                                  ;
   584                                  ;******************* END OF SPECIFICATIONS *************************************
   585                                  ;******************+ START OF PSEUDOCODE +**************************************
   586                                  ;
   587                                  ;	START Set_Mult_Block
   588                                  ;
   589                                  ;	count = start_count
   590                                  ;	search till count = 0
   591                                  ;		invoke Load_Regs
   592                                  ;		invoke Set_Block
   593                                  ;	exit if error
   594                                  ;		clear_count = start_count - current_count
   595                                  ;		loop till clear_count = 0
   596                                  ;			invoke Load_Regs
   597                                  ;			invoke Clr_Block
   598                                  ;		leave if error
   599                                  ;		end loop
   600                                  ;		set error status
   601                                  ;	orelse
   602                                  ;	endloop
   603                                  ;		set successful status
   604                                  ;	endsrch
   605                                  ;	if error status
   606                                  ;		load return code
   607                                  ;	endif
   608                                  ;	return
   609                                  ;
   610                                  ;	END Set_Mult_Block
   611                                  ;
   612                                  ;******************+  END  OF PSEUDOCODE +**************************************
   613                                  
   614                                     Procedure Set_Mult_Block,NEAR
   614          ******************       warning: proc Set_Mult_Block... [-w+user]
   615                                  
   616                                  ;	PUSH	DS			;ICE
   617                                  ;	push	bx			;ICE
   618                                  ;	push	ax			;ICE
   619                                  
   620                                  ;	mov	bx,0140H		;ICE
   621                                  ;	xor	ax,ax			;ICE
   622                                  ;	mov	ds,ax			;ICE
   623                                  ;	mov	ax,word ptr [ds:bx]	;ICE
   624                                  ;	mov	word ptr [ds:bx],ax	;ICE
   625                                  
   626                                  ;	pop	ax			;ICE
   627                                  ;	pop	bx			;ICE
   628                                  ;	POP	DS			;ICE
   629                                  
   630                                  
   631                                  
   632 000000C9 E8(0000)                   EnterCrit critShare			;				       ;AN000;
   633                                  
   634                                     ASSUME ES:NOTHING,DS:NOTHING 	;				       ;AN000;
   635                                  ;	      set up for loop
   636                                  
   637                                  ;      WE HAVE:   (from IBMDOS) 	|	  WE NEED:   (for Set_Block)
   638                                  
   639                                  ; (AL)	  = 0 - lock all		|    (BX)    = 0 lock all operations
   640                                  ;	  = 80- lock write		|	     = 1 lock write operations
   641                                  ; (CX)	  = the number of lock ranges	|    (CX:DX) = offset of area
   642                                  ; (DS:DX) = pointer to the range list	|    (SI:AX) = length of area
   643                                  ; (ES:DI) = SFT address 		|    (ES:DI) = SFT address
   644                                  
   645                                  ;  int 3
   646 000000CC 90                         nop
   647 000000CD 90                         nop
   648                                  
   649 000000CE 2E8C1E[0400]               mov	[cs:DS_Org],ds			;an000;save entry DS
   650                                  
   651 000000D3 161F                       Context DS				;				       ;AN000;
   652 000000D5 83F901                     CMP	CX,01h				;DO WE HAVE A COUNT?		       ;AN000;
   653                                  
   654                                  ;; $if	ae				; if the count was valid	       ;AN000;
   655                                  ;  $if	e				; if the count was valid	       ;AC006;
   656 000000D8 750A                       JNE D_$IF1
   657                                  
   658                                  ;;     PUSH CX				; count = start_count		       ;AN000;
   659                                  ;;     PUSH DX				; save pointer to range list	       ;AN000;
   660 000000DA 89D5                           MOV  BP,DX			; save current index into list	       ;AN000;
   661                                  ;;     AND  AX,0080H			; clear high byte and be sure low is   ;AN000;
   662                                  					; set if applicable
   663                                  ;;     ROL  AL,1			; move high bit to bit 0
   664                                  ;;     MOV  BX,AX			; SET UP TYPE OF LOCK		       ;AN000;
   665                                  
   666                                  ;;     $do				; loop till count = 0		       ;AN000;
   667                                  ;;	   cmp	cx,00			;an000;see if at end
   668                                  ;;     $leave e 			;an000;exit if at end
   669                                  ;;	   push cx			;an000;save cx - our counter
   670                                  ;;	   push di			;an000;save di - our SFT pointer
   671                                  load_regs equ Load_Regs	; NASM port label
   672 000000DC E80F00                         call load_regs			;an000;load the registers for call
   673                                  					;      to set_block
   674                                  set_block equ Set_Block	; NASM port label
   675 000000DF E85400                         call set_block			;an000;set the lock block
   676                                  ;;	   pop	di			;an000;restore our SFT pointer
   677                                  ;;	   pop	cx			;an000;restore cx - our counter
   678                                  ;;     $leave c 			;an000;on error exit loop
   679                                  ;;	   dec	cx			;an000;decrease counter
   680                                  ;;     $enddo				;an000;end loop
   681                                  
   682                                  ;;     $if  c				;an000;if an error occurred
   683                                  ;;	   pop	dx			;an000;restore range list pointer
   684                                  ;;	   pop	ax			;an000;obtain original count
   685                                  ;;	   sub	ax,cx			;an000;determine how many locks set
   686                                  ;;	   mov	cx,ax			;an000;set the loop counter with count
   687                                  ;;	   mov	bp,dx			;an000;set bp to point to range list
   688                                  ;;	   $do				;an000;while cx not = 0
   689                                  ;;	       cmp  cx,00		;an000;at end?
   690                                  ;;	   $leave e			;an000;yes, exit
   691                                  ;;	       push cx			;an000;save cx - our counter
   692                                  ;;	       push di			;an000;save di - our SFT pointer
   693                                  ;;	       call load_regs		;an000;load the registers for call
   694                                  					;      to clr_block
   695                                  ;;	       call clr_block		;an000;clear the locks
   696                                  ;;	       pop  di			;an000;restore our SFT pointer
   697                                  ;;	       pop  cx			;an000;restore cx - our counter
   698                                  ;;	   $leave c			;an000;on error exit
   699                                  ;;	       dec  cx			;an000;decrease counter
   700                                  ;;	   $enddo			;an000;
   701                                  ;;	   stc				;an000;signal an error occurred
   702                                  ;;     $else				;an000;no error occurred in locking
   703                                  ;;	   pop	ax			;an000;clear off the stack
   704                                  ;;	   pop	ax			;an000;   to balance it
   705                                  ;;	   clc				;an000;signal no error occurred
   706                                  ;;     $endif				;an000;
   707                                  ;  $else				;an000;cx was 0 - this is an error
   708 000000E2 EB01                       JMP SHORT D_$EN1
   709                                  D_$IF1:
   710 000000E4 F9                             stc				;an000;signal an error occurred
   711                                  ;  $endif				;				       ;an000;
   712                                  D_$EN1:
   713                                  
   714                                  ;  $if	c				; if there was an error 	       ;AN000;
   715 000000E5 7303                       JNC D_$IF4
   716 000000E7 B82100                         MOV  AX,error_lock_violation	; load the return code		       ;AN000;
   717                                  ;  $endif				; endif there was an error	       ;AN000;
   718                                  D_$IF4:
   719                                  
   720 000000EA E8(0000)                   LeaveCrit critShare			;				       ;AN000;
   721                                  
   722 000000ED C3                         ret					; return - all set		       ;AN000;
   723                                  
   724                                     EndProc Set_Mult_Block
   725                                  
   726                                     BREAK <Load_Regs - Load Registers for ?_Block call>
   727                                  
   728                                  ;******************* START OF SPECIFICATIONS ***********************************
   729                                  ;
   730                                  ;  NAME:	   Load_Regs - Load Registers for ?_Block calls
   731                                  ;
   732                                  ;  FUNCTION:	   This subroutine loads the High and Low Offsets and the
   733                                  ;		   High and Low lengths for Lock ranges from the Range List.
   734                                  ;
   735                                  ;  INPUT:	   (DS_Org:PB) - Range list entry to be loaded
   736                                  ;
   737                                  ;  OUTPUT:	   (DX) - Low Offset
   738                                  ;		   (CX) - High Offset
   739                                  ;		   (AX) - Low Length
   740                                  ;		   (SI) - High Length
   741                                  ;
   742                                  ;  REGISTERS USED: AX CX DX BP SI
   743                                  ;  (NOT RESTORED)
   744                                  ;
   745                                  ;  LINKAGE:	   Called by: Set_Mult_Block, Clr_Mult_Block
   746                                  ;
   747                                  ;  EXTERNAL	   none
   748                                  ;  REFERENCES:
   749                                  ;
   750                                  ;  NORMAL	   none
   751                                  ;  EXIT:
   752                                  ;
   753                                  ;  ERROR	   none
   754                                  ;  EXIT:
   755                                  ;
   756                                  ;  CHANGE	   04/15/87 - first release
   757                                  ;  LOG:
   758                                  ;
   759                                  ;******************* END OF SPECIFICATIONS *************************************
   760                                  ;******************+ START OF PSEUDOCODE +**************************************
   761                                  ;
   762                                  ;	  START Load_Regs
   763                                  ;
   764                                  ;	  recover index into range list
   765                                  ;	  advance pointer to next entry
   766                                  ;	  load DX - Low Offset
   767                                  ;	  load CX - High Offset
   768                                  ;	  load AX - Low Length
   769                                  ;	  load SI - High Length
   770                                  ;	  return
   771                                  ;
   772                                  ;	  END Load_Regs
   773                                  ;
   774                                  ;******************+  END  OF PSEUDOCODE +**************************************
   775                                  
   776                                     Procedure Load_Regs,NEAR
   776          ******************       warning: proc Load_Regs... [-w+user]
   777                                  
   778 000000EE 1E                         push ds				; save our DS			       ;an000;
   779 000000EF 2E8E1E[0400]               mov	ds,[cs:DS_Org]			; get range list segment	       ;an000;
   780 000000F4 89EE                       mov	si,bp				; recover pointer		       ;AN000;
   781 000000F6 83C508                     ADD	BP,08h				; move to next entry in list	       ;AN000;
   782 000000F9 8B14                       MOV	DX,[SI] 			; low position			       ;AN000;
   783 000000FB 8B4C02                     MOV	CX,[SI+2]			; high position 		       ;AN000;
   784 000000FE 8B4404                     MOV	AX,[SI+4]			; low length			       ;AN000;
   785 00000101 8B7406                     MOV	SI,[SI+6]			; high length			       ;AN000;
   786 00000104 1F                         pop	ds				; restore DS			       ;an000;
   787                                  
   788 00000105 C3                         ret					;				       ;AN000;
   789                                  
   790                                     EndProc Load_Regs
   791                                  
   792                                     BREAK <Clr_Mult_Block - Try to clear multiple locks>
   793                                  
   794                                  ;******************* START OF SPECIFICATIONS ***********************************
   795                                  ;
   796                                  ;  NAME:	   Clr_Mult_Block  -  Clear Multiple Block Locks
   797                                  ;
   798                                  ;  FUNCTION:	   Clr_Mult_Block removes the locks on 1 or more specified
   799                                  ;		   ranges of a file.  An error is returned if any lock range
   800                                  ;		   does not exactly match. Ranges of Locks are set via
   801                                  ;		   Set_Mult_Block.
   802                                  ;
   803                                  ;		   In DOS 3.3 only one lock range could be cleared at a time
   804                                  ;		   using Clr_Block.  For DOS 4.00 this routine will replace
   805                                  ;		   Clr_Block in the jump table and will make repeated calls
   806                                  ;		   to Set_Block in order to process 1 or more lock ranges.
   807                                  ;
   808                                  ;		   NOTE: - This is an all new interface to IBMDOS
   809                                  ;			 - an unlock all 'lock all' request will unlock both
   810                                  ;			   'lock all' and 'lock write'.
   811                                  ;			 - an unlock all 'lock write' request will not unlock
   812                                  ;			   'lock all's. It will only unlock 'lock write's.
   813                                  ;			  (if you can understand the above statement,
   814                                  ;			  understanding the code will be easy!)
   815                                  ;
   816                                  ;  INPUT:	   (AL) = 0 - lock all
   817                                  ;			= 80- lock write
   818                                  ;		   (CX) = the number of lock ranges - NB: all if -1 ***
   819                                  ;		   (DS:DX) = pointer to the range list
   820                                  ;		   (ES:DI) = SFT address
   821                                  ;		   User_ID = 16-bit user id of issuer
   822                                  ;		   Proc_ID = 16-bit process id of issuer
   823                                  ;		   (SS) = DOSGroup
   824                                  ;
   825                                  ;  OUTPUT:	   Lock records filled in for all blocks specified
   826                                  ;
   827                                  ;  REGISTERS USED: ALL but DS
   828                                  ;  (NOT RESTORED)
   829                                  ;
   830                                  ;  LINKAGE:	   IBMDOS Jump Table
   831                                  ;
   832                                  ;  EXTERNAL	   Invoke: Load_Regs, Set_Block, Clr_Block, Clr_List
   833                                  ;  REFERENCES:
   834                                  ;
   835                                  ;  NORMAL	   'C' clear if no error
   836                                  ;  EXIT:
   837                                  ;
   838                                  ;  ERROR	   'C' set if error
   839                                  ;  EXIT:	     (ax) = error code
   840                                  ;			       ('error_lock_violation' if conflicting locks)
   841                                  ;
   842                                  ;  CHANGE	04/15/87 - First release
   843                                  ;  LOG:
   844                                  ;
   845                                  ;******************* END OF SPECIFICATIONS *************************************
   846                                  ;******************+ START OF PSEUDOCODE +**************************************
   847                                  ;
   848                                  ;	START Clr_Mult_Block
   849                                  ;
   850                                  ;	if count is valid and
   851                                  ;	if file (SFT) is 'shared' then
   852                                  ;		if count = all
   853                                  ;			find first RLR
   854                                  ;			loop till all RLR cleared
   855                                  ;				if PROC_ID matches and
   856                                  ;				if UID matches and
   857                                  ;				if SFT matches then
   858                                  ;					if ulocking lock_all or
   859                                  ;					if this RLR is lock_write
   860                                  ;						clear the lock
   861                                  ;					endif
   862                                  ;				endif
   863                                  ;				find next RLR
   864                                  ;			end loop
   865                                  ;		else
   866                                  ;			invoke Clr_List
   867                                  ;		endif
   868                                  ;		set successful status
   869                                  ;	else
   870                                  ;		set error status
   871                                  ;	endif
   872                                  ;	if error
   873                                  ;		load return code
   874                                  ;	endif
   875                                  ;
   876                                  ;	ret
   877                                  ;
   878                                  ;	END Clr_Mult_Block
   879                                  ;
   880                                  ;******************+  END  OF PSEUDOCODE +**************************************
   881                                  
   882                                     Procedure clr_mult_block,NEAR
   882          ******************       warning: proc clr_mult_block... [-w+user]
   883                                  
   884                                  
   885                                  lock_all equ 0h
   886                                  
   887                                  ;	PUSH	DS			;ICE
   888                                  ;	push	bx			;ICE
   889                                  ;	push	ax			;ICE
   890                                  
   891                                  ;	mov	bx,0140H		;ICE
   892                                  ;	xor	ax,ax			;ICE
   893                                  ;	mov	ds,ax			;ICE
   894                                  ;	mov	ax,word ptr [ds:bx]	;ICE
   895                                  ;	mov	word ptr [ds:bx],ax	;ICE
   896                                  
   897                                  ;	pop	ax			;ICE
   898                                  ;	pop	bx			;ICE
   899                                  ;	POP	DS			;ICE
   900                                  
   901 00000106 E8(0000)                   EnterCrit critShare			;				       ;AN000;
   902                                  
   903                                     ASSUME ES:NOTHING,DS:NOTHING 	;				       ;AN000;
   904                                  
   905                                  ;  int 3
   906 00000109 90                         nop
   907 0000010A 90                         nop
   908                                  
   909 0000010B 2E8C1E[0400]               mov	[cs:DS_Org],DS			;an000;save entry DS
   910                                  
   911 00000110 161F                       Context DS				;				       ;AN000;
   912                                  
   913 00000112 83F901                     CMP	CX,01h				; do we have a count?		       ;AN000;
   914                                  ;; $IF	AE,AND				; IF A VALID COUNT
   915                                  ;  $IF	E,AND				; IF A VALID COUNT		       ;AC006;
   916 00000115 750E                       JNE D_$IF6
   917                                  sf_mft equ sf_MFT	; NASM port equate
   918 00000117 26837D3300                 cmp	word [es:di + sf_mft],0		; is this SFT shared?		       ;AN000;
   919                                  ;  $IF	NE				; AND IF FILE IS 'SHARED' THEN
   920 0000011C 7407                       JE D_$IF6
   921                                  
   922                                  ;      WE HAVE:   (from IBMDOS) 	|	  WE NEED:
   923                                  
   924                                  ; (AL)	  = 0 - lock all		|    (AX)    = 0 lock all operations
   925                                  ;	  = 80- lock write		|	     = 1 lock write operations
   926                                  ; (CX)	  = - 1  (unlock all locks)	|    (DS)    = CS
   927                                  ;					|    (DS:DI) = previous RLR
   928                                  ;					|    (DS:SI) = current RLR
   929                                  ; (ES:DI) = current SFT 		|
   930                                  
   931                                  ;;     and  ax,0080h			;be sure it is set right (mask 80 bit) ;AC002;
   932                                  					;    existing interface
   933                                  ;;     rol  al,1			;put high bit in bit 0		       ;AC002;
   934                                  
   935                                  ;;     CMP  CX,-1h			;				       ;AN000;
   936                                  ;;     $IF  E				; IF unlock all locks then	       ;AN000;
   937                                  
   938                                  ;;	   push cs			;				       ;AN000;
   939                                  ;;	   pop	ds			;				       ;AN000;
   940                                  ;;	   mov	cx,di			; ES:CX is the SFT		       ;AN004;
   941                                  
   942                                  ;	   ASSUME ds:nothing
   943                                  
   944                                  ;;	   mov	si,[es:di].sf_mft	; DS:SI points to MFT		       ;AN000;
   945                                  
   946                                  ;;	   lea	di,[si].mft_lptr	; DS:DI = addr of ptr to lock record   ;AN000;
   947                                  ;;	   mov	si,[di] 		; DS:SI = address of 1st lock record   ;AN000;
   948                                  
   949                                  ;;	   $DO				; loop through the RLR's               ;AN000;
   950                                  
   951                                  ;	DS:DI = points to previous RLR or MFT if no RLR.
   952                                  ;	DS:SI = points to current RLR
   953                                  ;	ES:CX = SFT address
   954                                  ;	AX    = lock type
   955                                  
   956                                  ;;	       and  si,si		; are we at the end of the chain?      ;AN000;
   957                                  ;;	   $LEAVE Z			; we'er done with CF = 0               ;AN000;
   958                                  
   959                                  ;;	       mov  bp,[si].rlr_pid	; get PROC_ID			       ;AN000;
   960                                  ;;	       cmp  bp,PROC_ID		; is it ours?			       ;AN000;
   961                                  ;;	       $IF  E,AND		;				       ;AN000;
   962                                  ;;	       mov  bp,es		;				       ;AN000;
   963                                  ;;	       cmp  bp,WORD PTR [si].rlr_sptr+2 ;			       ;AC004;
   964                                  ;;	       $IF  E,AND		;				       ;AN000;
   965                                  ;;	       cmp  cx,WORD PTR [si].rlr_sptr ; 			       ;AC004;
   966                                  ;;	       mov  si,[di]		; restore pointer to current (using    ;AN000;
   967                                  					;			     previous)
   968                                  ;;	       $IF  E			; if it is ours 		       ;AN000;
   969                                  
   970                                  ;	this is it. its OURS !
   971                                  
   972                                  ;;		   cmp	ax,lock_all	;				       ;AN000;
   973                                  
   974                                  ;;		   $IF	E,OR		; if unlocking all or		       ;AN000;
   975                                  
   976                                  ;;		   mov	bp,[si].rlr_type ; get lock type		       ;AN000;
   977                                  ;;		   cmp	bp,rlr_lall	; is it lock all?		       ;AN000;
   978                                  
   979                                  ;;		   $IF	NE		; if not a LOCK ALL lock	       ;AN000;
   980                                  
   981                                  ;	remove the RLR from the chain
   982                                  
   983                                  ;;		       mov  bx,[si].rlr_next ; get the pointer to the next RLR ;AN000;
   984                                  ;;		       mov  [di],bx	; install it in the last	       ;AN000;
   985                                  
   986                                  ;	put defunct lock record on the free chain
   987                                  
   988                                  ;;		       mov  bx,Frelock	;				       ;AN000;
   989                                  ;;		       mov  [si].rlr_next,bx ;				       ;AN000;
   990                                  ;;		       mov  Frelock,si	;				       ;AN000;
   991                                  ;;		       mov  si,di	; back up to last		       ;AN000;
   992                                  
   993                                  ;;		   $ENDIF		; should we unlock it		       ;AN000;
   994                                  
   995                                  ;;	       $ENDIF			; it was ours!			       ;AN000;
   996                                  
   997                                  ;	advance to next RLR
   998                                  
   999                                  ;;	       mov  di,si		; load address of next RLR	       ;AN000;
  1000                                  ;;	       mov  si,[di]		; update pointer to next RLR	       ;AN000;
  1001                                  
  1002                                  ;;	   $ENDDO			; loop back to the start	       ;AN000;
  1003                                  
  1004                                  ;;     $ELSE				; else, its a LIST !		       ;AN000;
  1005                                  
  1006                                  ;	      set up for loop
  1007                                  
  1008                                  ;      WE HAVE:   (from IBMDOS) 	|	  WE NEED:   (for Clr_Block)
  1009                                  
  1010                                  ; (AX)	  = 0 - lock all		|    (BX)    = 0 lock all operations
  1011                                  ;	  = 1 - lock write		|	     = 1 lock write operations
  1012                                  ; (CX)	  = the number of lock ranges	|    (CX:DX) = offset of area
  1013                                  ; (DS:DX) = pointer to the range list	|    (SI:AX) = length of area
  1014                                  ; (ES:DI) = SFT address 		|    (ES:DI) = SFT address
  1015                                  
  1016                                  ;;	   PUSH CX			; count = start_count		       ;AN000;
  1017                                  ;;	   PUSH DX			; save pointer to range list	       ;AN000;
  1018 0000011E 89D5                           MOV  BP,DX			; save current index into list	       ;AN000;
  1019                                  ;;	   MOV	BX,AX			; SET UP TYPE OF LOCK		       ;AN000;
  1020                                  
  1021 00000120 E80C00                         call Clr_List			; call Clr_List to process the list    ;AN000;
  1022                                  
  1023                                  ;;     $ENDIF				;				       ;AN000;
  1024                                  
  1025                                  ;  $ELSE				; NOT VALID
  1026 00000123 EB01                       JMP SHORT D_$EN6
  1027                                  D_$IF6:
  1028                                  
  1029 00000125 F9                             STC				;				       ;AN000;
  1030                                  
  1031                                  ;  $ENDIF				; VALID/INVALID 		       ;AN000;
  1032                                  D_$EN6:
  1033                                  
  1034                                  ;  $IF	C				; if carry is set		       ;AN000;
  1035 00000126 7303                       JNC D_$IF9
  1036 00000128 B82100                         MOV  AX,error_lock_violation	; load error condition		       ;AN000;
  1037                                  ;  $ENDIF				; carry not set 		       ;AN000;
  1038                                  D_$IF9:
  1039                                  
  1040 0000012B E8(0000)                   LeaveCrit critShare			;				       ;AN000;
  1041                                  
  1042 0000012E C3                         ret					; return - all set		       ;AN000;
  1043                                  
  1044                                     EndProc clr_mult_block
  1045                                  
  1046                                     BREAK <Clr_List - Clear a list of user specified locks>
  1047                                  
  1048                                  ;******************* START OF SPECIFICATIONS ***********************************
  1049                                  ;
  1050                                  ;  NAME:	   Clr_List  -	Clear a list of user specified locks
  1051                                  ;
  1052                                  ;  FUNCTION:	   Clr_List makes multiple calls to Clr_Block to clear
  1053                                  ;		   multiple lock ranges of a file.  An error is returned
  1054                                  ;		   if any lock range does not exactly match. Ranges of
  1055                                  ;		   Locks are then set via Set_Mult_Block.
  1056                                  ;
  1057                                  ;
  1058                                  ;  INPUT:	   (BX)    = 0 lock all operations
  1059                                  ;			   = 1 lock write operations
  1060                                  ;		   (CX:DX) = offset of area
  1061                                  ;		   (SI:AX) = length of area
  1062                                  ;		   (ES:DI) = SFT address
  1063                                  ;		   (SS:SP+2)= original index \ see FRAME struc
  1064                                  ;		   (SS:SP+4)= original count /
  1065                                  ;
  1066                                  ;  OUTPUT:	   Lock records removed for all blocks specified
  1067                                  ;		   Stack cleard on return
  1068                                  ;
  1069                                  ;  REGISTERS USED: ALL but DS
  1070                                  ;  (NOT RESTORED)
  1071                                  ;
  1072                                  ;  LINKAGE:	   IBMDOS Jump Table
  1073                                  ;
  1074                                  ;  EXTERNAL	   Invoke: Load_Regs, Set_Block, Clr_Block
  1075                                  ;  REFERENCES:
  1076                                  ;
  1077                                  ;  NORMAL	   'C' clear if no error
  1078                                  ;  EXIT:
  1079                                  ;
  1080                                  ;  ERROR	   'C' set if error
  1081                                  ;  EXIT:	     (ax) = error code
  1082                                  ;			       ('error_lock_violation' if conflicting locks)
  1083                                  ;
  1084                                  ;  CHANGE	04/15/87 - First release
  1085                                  ;  LOG:
  1086                                  ;
  1087                                  ;******************* END OF SPECIFICATIONS *************************************
  1088                                  ;******************+ START OF PSEUDOCODE +**************************************
  1089                                  ;
  1090                                  ;	START Clr_List
  1091                                  ;
  1092                                  ;	search till count = 0
  1093                                  ;		set up for call
  1094                                  ;		call clr_Block
  1095                                  ;	exit if c
  1096                                  ;		clear_count = start_count - current_count
  1097                                  ;		loop till clear_count = 0
  1098                                  ;			set up for call
  1099                                  ;			call Set_Block
  1100                                  ;		end loop
  1101                                  ;		set error status
  1102                                  ;	orelse
  1103                                  ;	endloop
  1104                                  ;		set successful status
  1105                                  ;	endsrch
  1106                                  ;	return
  1107                                  ;
  1108                                  ;	END Clr_List
  1109                                  ;
  1110                                  ;******************+  END  OF PSEUDOCODE +**************************************
  1111                                  
  1112                                     Procedure Clr_List,NEAR
  1112          ******************       warning: proc Clr_List... [-w+user]
  1113                                  
  1114                                  ;; $do					;an000;while cx not = 0
  1115                                  ;;     cmp  cx,00			;an000;at end?
  1116                                  ;; $leave e				;an000;yes
  1117                                  ;;     push cx				;an000;save cx - our counter
  1118                                  ;;     push di				;an000;save di - our SFT pointer
  1119 0000012F E8BCFF                     call load_regs			;an000;set up for clr_block call
  1120                                  ;;     push bp				; save pointer to range entry	       ;AN000;
  1121                                  clr_block equ Clr_Block	; NASM port label
  1122 00000132 E84300                     call clr_block			;an000;remove the lock
  1123                                  ;;     pop  bp				; recover pointer to range entry       ;AN000;
  1124                                  ;;     pop  di				;an000;restore our SFT pointer
  1125                                  ;;     pop  cx				;an000;restore cx - our counter
  1126                                  ;; $leave c				;an000;leave on error
  1127                                  ;;     dec  cx				;an000;decrease counter
  1128                                  ;; $enddo				;an000;
  1129                                  
  1130                                  ;; $if	c				;an000;an error occurred
  1131                                  ;;     push bp				;an000;save bp
  1132                                  ;;     mov  bp,sp			;an000;get sp
  1133                                  ;;     mov  dx,[bp].parm_1		;an000;recover original index
  1134                                  ;;     mov  ax,[bp].Parm_2		; original count		       ;AN000;
  1135                                  ;;     pop  bp
  1136                                  ;;     SUB  AX,CX			; how many did we do?		       ;AN000;
  1137                                  ;;     MOV  CX,AX			; set up the loop		       ;AN000;
  1138                                  ;;     MOV  BP,DX			; save the index		       ;AN000;
  1139                                  
  1140                                  ;;     $DO				;				       ;AN000;
  1141                                  ;;	   cmp	cx,00			;an000;at end?
  1142                                  ;;     $leave e 			;an000;yes
  1143                                  ;;	   push cx			;an000;save cx - our counter
  1144                                  ;;	   push di			;an000;save di - our SFT pointer
  1145                                  ;;	   call load_regs		;an000;set up for set_block call
  1146                                  ;;	   call set_block		;an000;reset the locks
  1147                                  ;;	   pop	di			;an000;restore our SFT pointer
  1148                                  ;;	   pop	cx			;an000;restore cx - our counter
  1149                                  ;;     $leave c 			;an000;leave on error
  1150                                  ;;	   dec	cx			;an000;decrease counter
  1151                                  ;;     $enddo				;an000;
  1152                                  ;;     stc				;an000;signal an error
  1153                                  ;; $else				;an000;
  1154                                  ;;     clc				;an000;signal no error
  1155                                  ;; $endif				;an000;
  1156                                  
  1157                                  ;; ret	4				; return (clear Parm_1 & Parm_2)       ;AN000;
  1158 00000135 C3                         ret					; return (clear Parm_1 & Parm_2)       ;AC006;
  1159                                  
  1160                                     EndProc Clr_List
  1161                                  
  1162                                  
  1163                                     BREAK <Set_Block - Try to set a lock>
  1164                                  
  1165                                  ;******************* START OF SPECIFICATIONS ***********************************
  1166                                  ;
  1167                                  ;  NAME:	   Set_Block - set byte range lock on a file
  1168                                  ;
  1169                                  ;  FUNCTION:	   Set_Block sets a lock on a specified range of a file.  An
  1170                                  ;		   error is returned if the lock conflicts with another.
  1171                                  ;		   Locks are cleared via clr_block.
  1172                                  ;
  1173                                  ;  INPUT:	   (ES:DI) = SFT address
  1174                                  ;		   (CX:DX) = offset of area
  1175                                  ;		   (SI:AX) = length of area
  1176                                  ;		   (BX)    = 0 lock all operations
  1177                                  ;			   = 1 lock write operations
  1178                                  ;		   User_ID = 16-bit user id of issuer
  1179                                  ;		   Proc_ID = 16-bit process id of issuer
  1180                                  ;		   (SS) = DOSGroup
  1181                                  ;
  1182                                  ;  OUTPUT:	   Lock records removed for all blocks specified
  1183                                  ;
  1184                                  ;  REGISTERS USED: ALL but DS, BP
  1185                                  ;  (NOT RESTORED)
  1186                                  ;
  1187                                  ;  LINKAGE:	   Invoked by: Set_Mult_Block
  1188                                  ;
  1189                                  ;  EXTERNAL	   Invoke: CLP (SLE), OFL
  1190                                  ;  REFERENCES:
  1191                                  ;
  1192                                  ;  NORMAL	   'C' clear if no error
  1193                                  ;  EXIT:
  1194                                  ;
  1195                                  ;  ERROR	   'C' set if error
  1196                                  ;  EXIT:
  1197                                  ;
  1198                                  ;  CHANGE	04/15/87 - lock only write support
  1199                                  ;  LOG:
  1200                                  ;
  1201                                  ;******************* END OF SPECIFICATIONS *************************************
  1202                                  ;******************+ START OF PSEUDOCODE +**************************************
  1203                                  ;
  1204                                  ;	START Set_Block
  1205                                  ;
  1206                                  ;	if a valid SFT and
  1207                                  ;	invoke CLP
  1208                                  ;	if no lock conflicts and
  1209                                  ;	invoke OFL
  1210                                  ;	if empty lock record available
  1211                                  ;		store SFT pointer
  1212                                  ;		store lock range
  1213                                  ;		add RLR to the chain
  1214                                  ;		store PROC_ID
  1215                                  ;		store rlr_type
  1216                                  ;		set successful return status
  1217                                  ;	else
  1218                                  ;		set error return status
  1219                                  ;	endif
  1220                                  ;	return
  1221                                  ;
  1222                                  ;	END Set_Block
  1223                                  ;
  1224                                  ;******************+  END  OF PSEUDOCODE +**************************************
  1225                                  
  1226                                     Procedure Set_Block,NEAR
  1226          ******************       warning: proc Set_Block... [-w+user]
  1227                                  
  1228                                     ASSUME ES:NOTHING,DS:NOTHING
  1229                                  
  1230 00000136 161F                       Context DS
  1231                                  
  1232 00000138 55                         push bp				; preserve (bp) 		       ;AN000;
  1233 00000139 1E                         push ds				; preserve (ds)
  1234                                  ;; push bx				; preserve (bx) 		       ;AN000;
  1235 0000013A 26837D3300                 cmp	word [es:di + sf_mft],ZERO
  1236                                  ;  $if	nz,and				; if file is SHARED and 	       ;AC000;
  1237 0000013F 7430                       JZ D_$IF11
  1238 00000141 57                         push di
  1239                                  clp equ CLP	; NASM port label
  1240 00000142 E87800                     call clp				; do common setup code
  1241                                  
  1242                                     ASSUME DS:NOTHING
  1243                                  
  1244 00000145 5D                         pop	bp
  1245                                  ;  $if	nc,and				; if no (lock conflict) error and      ;AC000;
  1246 00000146 7229                       JC D_$IF11
  1247                                  
  1248                                  ;	Its ok to set this lock.  Get a free block and fill it in
  1249                                  ;	(es:bp) = sft
  1250                                  ;	(ds:si) = pointer to name record
  1251                                  ;	(ax:bx) = fba lock area
  1252                                  ;	(cx:dx) = lba lock area
  1253                                  ;	(ds:di) = pointer to pointer to previous lock
  1254                                  ;	(TOS)	= saved (bx)
  1255                                  ;	(TOS+1) = saved (ds)
  1256                                  ;	(TOS+2) = saved (bp)
  1257                                  
  1258                                  OFL equ ofl	; NASM port label
  1259 00000148 E8(0000)                   call OFL				; (ds:di) = pointer to new, orphan lock record
  1260                                  ;  $if	nc				; if space available		       ;AC000;
  1261 0000014B 7224                       JC D_$IF11
  1262 0000014D 896D0A                         mov  WORD PTR [di + rlr_sptr],bp	; store SFT offset
  1263 00000150 8C450C                         mov  WORD PTR [di + rlr_sptr + 2],es ; store SFT offset
  1264 00000153 894504                         mov  [di + rlr_fba + 2],ax
  1265 00000156 895D02                         mov  [di + rlr_fba],bx		; store lock range
  1266 00000159 894D08                         mov  [di + rlr_lba + 2],cx
  1267 0000015C 895506                         mov  [di + rlr_lba],dx
  1268                                  
  1269                                  ;	add to front of chain
  1270                                  ;
  1271                                  ;	(ds:si) = fwa MFT name record
  1272                                  
  1273 0000015F 8B4404                         mov  ax,[si + mft_lptr]
  1274 00000162 8905                           mov  [di + rlr_next],ax
  1275 00000164 897C04                         mov  [si + mft_lptr],di
  1276                                  ;
  1277                                  ; Set process ID of lock
  1278                                  ;
  1279                                  proc_id equ Proc_ID	; NASM port label
  1280 00000167 36A1[0000]                     mov  ax,[ss:proc_id]
  1281 0000016B 89450E                         mov  [di + rlr_pid],ax
  1282                                  
  1283                                  ;
  1284                                  ;;     pop  bx				; recover lock type		       ;AN000;
  1285                                  ;;     push bx				; restore the stack		       ;AN000;
  1286                                  ;;     mov  [di].rlr_type,bx		; set the rlr_type field	       ;AN000;
  1287 0000016E F8                             clc				; we finished OK
  1288                                  
  1289                                  ;  $else				;				       ;AC000;
  1290 0000016F EB04                       JMP SHORT D_$EN11
  1291                                  D_$IF11:
  1292                                  
  1293 00000171 B82100                         mov  ax,error_lock_violation
  1294 00000174 F9                             stc
  1295                                  
  1296                                  ;  $endif				;				       ;AC000;
  1297                                  D_$EN11:
  1298                                  
  1299                                  ;; pop	bx				;				       ;AN000;
  1300 00000175 1F                         pop	ds
  1301 00000176 5D                         pop	bp				;				       ;AC000;
  1302                                  
  1303 00000177 C3                         ret					; return - all set
  1304                                  
  1305                                     EndProc Set_Block
  1306                                  
  1307                                     BREAK <Clr_Block - Try to clear a lock>
  1308                                  
  1309                                  ;******************* START OF SPECIFICATIONS ***********************************
  1310                                  ;
  1311                                  ;  NAME:	   Clr_Block - clear byte range lock on a file
  1312                                  ;
  1313                                  ;  FUNCTION:	   Clr_Block clears a lock on a specified range of a file.
  1314                                  ;		   Locks are set via set_block.
  1315                                  ;
  1316                                  ;  INPUT:	   (ES:DI) = SFT address
  1317                                  ;		   (CX:DX) = offset of area
  1318                                  ;		   (SI:AX) = length of area
  1319                                  ;		   (BX)    = 0 lock all operations
  1320                                  ;			   = 1 lock write operations
  1321                                  ;		   User_ID = 16-bit user id of issuer
  1322                                  ;		   Proc_ID = 16-bit process id of issuer
  1323                                  ;		   (SS) = DOSGroup
  1324                                  ;
  1325                                  ;  OUTPUT:	   Lock record removed for block specified.
  1326                                  ;
  1327                                  ;  REGISTERS USED: ALL but DS
  1328                                  ;  (NOT RESTORED)
  1329                                  ;
  1330                                  ;  LINKAGE:	   Invoked by:	Clr_Mult_Block
  1331                                  ;
  1332                                  ;  EXTERNAL	   Invoke: CLP (SLE), OFL
  1333                                  ;  REFERENCES:
  1334                                  ;
  1335                                  ;  NORMAL	   'C' clear if no error
  1336                                  ;  EXIT:
  1337                                  ;
  1338                                  ;  ERROR	   'C' set if error
  1339                                  ;  EXIT:	     (ax) = error code
  1340                                  ;			       ('error_lock_violation' if conflicting locks or
  1341                                  ;			       range does not exactly match previous lock)
  1342                                  ;
  1343                                  ;  CHANGE	04/15/87 - lock only write support
  1344                                  ;  LOG:
  1345                                  ;
  1346                                  ;******************* END OF SPECIFICATIONS *************************************
  1347                                  ;******************+ START OF PSEUDOCODE +**************************************
  1348                                  ;
  1349                                  ;	START Clr_Block
  1350                                  ;
  1351                                  ;	if file is SHARED and
  1352                                  ;	if lock is valid and
  1353                                  ;	if SFT matches and
  1354                                  ;	if PROC_ID matches
  1355                                  ;		if lock_reqest = lock_type
  1356                                  ;			unchain the lock
  1357                                  ;			put defunct lock on free chain
  1358                                  ;			clear error status
  1359                                  ;		else
  1360                                  ;			set error status
  1361                                  ;		endif
  1362                                  ;	else
  1363                                  ;		flush the stack
  1364                                  ;		set error status
  1365                                  ;	endif
  1366                                  ;	if error
  1367                                  ;		load return code
  1368                                  ;	endif
  1369                                  ;	return
  1370                                  ;
  1371                                  ;	END Clr_Block
  1372                                  ;
  1373                                  ;******************+  END  OF PSEUDOCODE +**************************************
  1374                                  
  1375                                     Procedure Clr_Block,NEAR
  1375          ******************       warning: proc Clr_Block... [-w+user]
  1376                                  
  1377                                     ASSUME ES:NOTHING,DS:NOTHING
  1378                                  
  1379 00000178 161F                       Context DS
  1380 0000017A 1E                         push ds
  1381                                  ;; push bx				; save type of operation	       ;AN000;
  1382 0000017B 26837D3300                 cmp	word [es:di + sf_mft],ZERO
  1383                                  
  1384                                  ;  $if	nz,and				; if file is SHARED and 	       ;AC000;
  1385 00000180 7433                       JZ D_$IF14
  1386                                  
  1387 00000182 57                         push di
  1388 00000183 E83700                     call clp				; do common setup code
  1389                                  
  1390                                     ASSUME DS:NOTHING
  1391                                  
  1392 00000186 5D                         pop	bp				; ES:BP points to sft.
  1393                                  ;; pop	bx				; recover the type of operation        ;AN000;
  1394                                  
  1395                                  ;  $if	c,and				; if lock exists and		       ;AC000;
  1396 00000187 732C                       JNC D_$IF14
  1397                                  ;  $if	z,and				; if range given correctly and	       ;AC000;
  1398 00000189 752A                       JNZ D_$IF14
  1399                                  ;
  1400                                  ;	We've got the lock
  1401                                  ;
  1402                                  ;	(ds:di) = address of pointer (offset) to previous lock record
  1403                                  ;	(es:BP) = sft address
  1404                                  ;
  1405                                  ; Now comes the tricky part.  Is the lock for us?  Does the lock match the SFT
  1406                                  ; that was given us?  If not, then error.
  1407                                  ;
  1408 0000018B 8B35                       mov	si,[di] 			; (DS:SI) = address of lock record
  1409 0000018D 396C0A                     cmp	word ptr [si + rlr_sptr],bp
  1410                                  
  1411                                  ;  $if	z,and				; if SFT matches and		       ;AC000;
  1412 00000190 7523                       JNZ D_$IF14
  1413                                  
  1414 00000192 8CC5                       mov	bp,es
  1415 00000194 396C0C                     cmp	word ptr [si + rlr_sptr + 2],bp
  1416                                  ;  $if	z,and				; (check both words of SFT pointer)    ;AC000;
  1417 00000197 751C                       JNZ D_$IF14
  1418 00000199 368B2E[0000]               mov	bp,[ss:proc_id]
  1419 0000019E 396C0E                     cmp	[si + rlr_pid],bp
  1420                                  
  1421                                  ;; $if	z,and				; if PROC_ID matches		       ;AC000;
  1422                                  ;  $if	z				; if PROC_ID matches		       ;AC006;
  1423 000001A1 7512                       JNZ D_$IF14
  1424                                  ;
  1425                                  ; Make sure that the type of request and the lock type match
  1426                                  ;
  1427                                  ;; cmp	bx,lock_all			;				       ;AN000;
  1428                                  
  1429                                  ;; $IF	E,OR				; if unlocking all or		       ;AN000;
  1430                                  
  1431                                  ;; mov	bp,[si].rlr_type		; get lock type 		       ;AN000;
  1432                                  ;; cmp	bp,rlr_lall			; is it lock all?		       ;AN000;
  1433                                  
  1434                                  ;; $IF	NE				; if not a LOCK ALL lock	       ;AN000;
  1435                                  ;
  1436                                  ; The locks match the proper open invocation.  Unchain the lock
  1437                                  ;
  1438 000001A3 8B04                           mov  ax,[si + rlr_next]
  1439 000001A5 8905                           mov  [di],ax			; chain it out
  1440                                  
  1441                                  ;	put defunct lock record on the free chain
  1442                                  ;
  1443                                  ;	(ds:si) = address of freed lock rec
  1444                                  
  1445 000001A7 2EA1[0000]                     mov  ax,[cs:Frelock]
  1446 000001AB 8904                           mov  [si + rlr_next],ax
  1447 000001AD 2E8936[0000]                   mov  [cs:Frelock],si
  1448 000001B2 F8                             clc
  1449                                  
  1450                                  ;  $else				; we have an error		       ;AC000;
  1451 000001B3 EB01                       JMP SHORT D_$EN14
  1452                                  D_$IF14:
  1453                                  
  1454 000001B5 F9                             stc
  1455                                  
  1456                                  ;  $endif				; Endif - an error		       ;AC000;
  1457                                  D_$EN14:
  1458                                  
  1459                                  ;  $if	c				; If an error was found 	       ;AC000;
  1460 000001B6 7303                       JNC D_$IF17
  1461                                  
  1462 000001B8 B82100                         mov  ax,error_lock_violation
  1463                                  
  1464                                  ;  $endif				; Endif - an error was found	       ;AC000;
  1465                                  D_$IF17:
  1466                                  
  1467 000001BB 1F                         pop	ds				; restore DS
  1468                                  
  1469 000001BC C3                         ret
  1470                                  
  1471                                  
  1472                                     EndProc Clr_Block
  1473                                  
  1474                                     BREAK <CLP - Common Lock Preamble>
  1475                                  
  1476                                  ;******************* START OF SPECIFICATIONS ***********************************
  1477                                  ;
  1478                                  ;  NAME:	   CLP - Common Lock Preamble
  1479                                  ;
  1480                                  ;  FUNCTION:	   This routine contains a common code fragment for set_block
  1481                                  ;		   and clr_block.
  1482                                  ;
  1483                                  ;  INPUT:	   (ES:DI) = SFT address
  1484                                  ;		   (CX:DX) = offset of area
  1485                                  ;		   (SI:AX) = length of area
  1486                                  ;		   User_ID = 16-bit user id of issuer
  1487                                  ;		   Proc_ID = 16-bit process id of issuer
  1488                                  ;		   (SS) = (DS) = DOSGroup
  1489                                  ;
  1490                                  ;  OUTPUT:	   (ds:si) = MFT address
  1491                                  ;
  1492                                  ;  REGISTERS USED: ALL but ES
  1493                                  ;  (NOT RESTORED)
  1494                                  ;
  1495                                  ;  LINKAGE:	   Invoked by: Set_Block, Clr_Block
  1496                                  ;
  1497                                  ;  EXTERNAL	   Invoke: SLE
  1498                                  ;  REFERENCES:
  1499                                  ;
  1500                                  ;  NORMAL	   'C' clear if no overlap
  1501                                  ;  EXIT:	       (ax:bx) = offset of first byte in range
  1502                                  ;		       (cx:dx) = offset of last byte in range
  1503                                  ;
  1504                                  ;  ERROR	   'C' set if overlap
  1505                                  ;  EXIT:	   'Z' set if 1-to-1 match
  1506                                  ;		       (di) points to previous lock
  1507                                  ;
  1508                                  ;  CHANGE	04/15/87 - lock only write support
  1509                                  ;  LOG:
  1510                                  ;
  1511                                  ;******************* END OF SPECIFICATIONS *************************************
  1512                                  ;******************+ START OF PSEUDOCODE +**************************************
  1513                                  ;
  1514                                  ;	START CLP
  1515                                  ;
  1516                                  ;	shuffle arguments
  1517                                  ;	if valid length
  1518                                  ;		invoke SLE
  1519                                  ;		set successful return status
  1520                                  ;	else
  1521                                  ;		set error return status
  1522                                  ;	endif
  1523                                  ;	return
  1524                                  ;
  1525                                  ;	END CLP
  1526                                  ;
  1527                                  ;******************+  END  OF PSEUDOCODE +**************************************
  1528                                  
  1529                                     Procedure CLP,NEAR
  1529          ******************       warning: proc CLP... [-w+user]
  1530                                  
  1531 000001BD 89D3                       mov	bx,dx				; shuffle arguments
  1532 000001BF 92                         xchg dx,ax
  1533 000001C0 91                         xchg ax,cx				; (ax:bx) = offset
  1534 000001C1 89F1                       mov	cx,si				; (cx:dx) = length
  1535                                  
  1536 000001C3 09D6                       or	si,dx				; see if length is 0
  1537                                  
  1538                                  ;  $if	nz,and				; if length is > 0 and		       ;AC000;
  1539 000001C5 7424                       JZ D_$IF19
  1540                                  
  1541 000001C7 01DA                       add	dx,bx
  1542 000001C9 11C1                       adc	cx,ax				; (cx:dx) = lba+1
  1543                                  
  1544                                  ;  $if	nc,or				; no carry is ok		       ;AC000;
  1545 000001CB 7306                       JNC D_$LL19
  1546                                  
  1547 000001CD 89D6                       mov	si,dx
  1548 000001CF 09CE                       or	si,cx
  1549                                  
  1550                                  ;  $if	z				; if !> 0 then			       ;AC000;
  1551 000001D1 7518                       JNZ D_$IF19
  1552                                  D_$LL19:
  1553                                  
  1554 000001D3 83EA01                         sub  dx,1			; (cx:dx) = lba of locked region
  1555 000001D6 83D900                         sbb  cx,0
  1556                                  
  1557 000001D9 0E                             push cs
  1558 000001DA 1F                             pop  ds
  1559                                  ;   (es:di) is sft
  1560 000001DB 56                             push si
  1561 000001DC 268B7533                       mov  si,[es:di + sf_mft]
  1562 000001E0 56                             push si
  1563 000001E1 BF0100                         mov  di,1			; Find own locks
  1564                                  SLE equ sle	; NASM port label
  1565 000001E4 E8(0000)                       call SLE
  1566                                  ; di points to previous lock record
  1567 000001E7 5E                             pop  si
  1568 000001E8 5D                             pop  bp
  1569                                  
  1570                                  ;  $else				; we have an error		       ;AC000;
  1571 000001E9 EB07                       JMP SHORT D_$EN19
  1572                                  D_$IF19:
  1573                                  
  1574 000001EB 31F6                           xor  si,si
  1575 000001ED 46                             inc  si				; carry unchanged, zero reset
  1576 000001EE B82100                         mov  ax,error_lock_violation	; assume error
  1577 000001F1 F9                             stc
  1578                                  
  1579                                  ;  $endif				; endif - we have an error	       ;AC000;
  1580                                  D_$EN19:
  1581                                  
  1582 000001F2 C3                         ret
  1583                                  
  1584                                     EndProc CLP
  1585                                  
  1586                                     BREAK <Chk_Block - See if the specified I/O violates locks>
  1587                                  
  1588                                  ;******************* START OF SPECIFICATIONS ***********************************
  1589                                  ;
  1590                                  ;  NAME:	   Chk_Block - check range lock on a file
  1591                                  ;
  1592                                  ;  FUNCTION:	   Chk_Block is called to interogate the lock status of a
  1593                                  ;		   region of a file.
  1594                                  ;
  1595                                  ;  NOTE:	   This routine is called for every disk I/O operation
  1596                                  ;		   and MUST BE FAST
  1597                                  ;
  1598                                  ;  INPUT:	   (ES:DI) points to an SFT structure
  1599                                  ;		   (AL) = 80h - Write operation  = 0 - any non write operation
  1600                                  ;		   (CX) is the number of bytes being read or written
  1601                                  ;		   BytPos is a long (low first) offset into the file
  1602                                  ;			      of the I/O
  1603                                  ;		   User_ID = 16-bit user id of issuer
  1604                                  ;		   Proc_ID = 16-bit process id of issuer
  1605                                  ;		   (SS) = DOSGroup
  1606                                  ;
  1607                                  ;  OUTPUT:	   CF set according to status and presence of locks (see below)
  1608                                  ;
  1609                                  ;  REGISTERS USED: ALL	but ES,DI,CX,DS
  1610                                  ;  (NOT RESTORED)
  1611                                  ;
  1612                                  ;  LINKAGE:	   IBMDOS Jump Table
  1613                                  ;
  1614                                  ;  NORMAL	   'C' clear if no error
  1615                                  ;  EXIT:
  1616                                  ;
  1617                                  ;  ERROR	   'C' set if error
  1618                                  ;  EXIT:	     (ax) = error code
  1619                                  ;			       ('error_lock_violation' if conflicting locks)
  1620                                  ;
  1621                                  ;  CHANGE	04/15/87 - lock only write support
  1622                                  ;  LOG:
  1623                                  ;
  1624                                  ;******************* END OF SPECIFICATIONS *************************************
  1625                                  ;******************+ START OF PSEUDOCODE +**************************************
  1626                                  ;
  1627                                  ;	START Chk_Block
  1628                                  ;
  1629                                  ;	if shared SFT and
  1630                                  ;	if locks exist
  1631                                  ;		invoke SLE
  1632                                  ;		if lock conflicts occur (error)
  1633                                  ;			if this is !write operation and
  1634                                  ;			if a write lock found
  1635                                  ;				set successfull status
  1636                                  ;			else
  1637                                  ;				set error status
  1638                                  ;			endif
  1639                                  ;		else no error
  1640                                  ;			flush stack
  1641                                  ;		endif
  1642                                  ;	endif
  1643                                  ;
  1644                                  ;	ret
  1645                                  ;
  1646                                  ;	END Chk_Block
  1647                                  ;
  1648                                  ;******************+  END  OF PSEUDOCODE +**************************************
  1649                                  
  1650                                     Procedure Chk_Block,NEAR
  1650          ******************       warning: proc Chk_Block... [-w+user]
  1651                                  
  1652                                     ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP
  1653                                  
  1654                                  write_op equ 080h			; write operation requested	       ;AN000;
  1655                                  lock_all equ 0h 			; lock all specified		       ;AN000;
  1656                                  
  1657                                  ;	PUSH	DS			;ICE
  1658                                  ;	push	bx			;ICE
  1659                                  ;	push	ax			;ICE
  1660                                  
  1661                                  ;	mov	bx,0140H		;ICE
  1662                                  ;	xor	ax,ax			;ICE
  1663                                  ;	mov	ds,ax			;ICE
  1664                                  ;	mov	ax,word ptr [ds:bx]	;ICE
  1665                                  ;	mov	word ptr [ds:bx],ax	;ICE
  1666                                  
  1667                                  ;	pop	ax			;ICE
  1668                                  ;	pop	bx			;ICE
  1669                                  ;	POP	DS			;ICE
  1670 000001F3 E8(0000)                   EnterCrit critShare
  1671                                  
  1672                                  ;  int 3
  1673 000001F6 90                         nop
  1674 000001F7 90                         nop
  1675                                  
  1676 000001F8 06                         PUSH ES
  1677 000001F9 57                         PUSH DI
  1678 000001FA 51                         PUSH CX
  1679 000001FB 1E                         PUSH DS
  1680 000001FC 26837D3300                 cmp	word [es:di + sf_mft],0
  1681                                  
  1682                                  ;  $if	nz,and				; if the file is SHARED and	       ;AC000;
  1683 00000201 742C                       JZ D_$IF22
  1684                                  
  1685 00000203 0E                         push cs
  1686 00000204 1F                         pop	ds
  1687 00000205 268B7533                   mov	si,[es:di + sf_MFT]		; (DS:SI) = address of MFT record
  1688 00000209 F74404FFFF                 test word [si + mft_lptr],-1
  1689                                  
  1690                                  ;  $if	nz,and				; if there are locks on this file and  ;AC000;
  1691 0000020E 741F                       JZ D_$IF22
  1692                                  
  1693 00000210 83E901                     sub	cx,1				; (cx) = count-1
  1694 00000213 F5                         cmc
  1695                                  
  1696                                  ;  $if	c				; there are bytes to lock	       ;AC000;
  1697 00000214 7319                       JNC D_$IF22
  1698                                  
  1699                                  ;;     push ax				; preserve type of operation	       ;AN000;
  1700                                  					; DOS passes AL = 80 for writes
  1701                                  					;		= 00 for reads
  1702                                  
  1703 00000216 36A1[0200]                     mov  ax,WORD PTR [ss:BytPos+2]
  1704 0000021A 368B1E[0000]                   mov  bx,WORD PTR [ss:BytPos]		; (ax:bx) = offset
  1705 0000021F 89CA                           mov  dx,cx
  1706 00000221 29C9                           sub  cx,cx
  1707 00000223 01DA                           add  dx,bx
  1708 00000225 11C1                           adc  cx,ax			; (cx:dx) = lba of lock area
  1709 00000227 29FF                           sub  di,di			; ignore own locks
  1710 00000229 E8(0000)                       call SLE
  1711                                  ;;     pop  ax				; recover type of opperation	       ;AN000;
  1712                                  
  1713                                  ;   upon return DS:SI points to the RLR with the conflict
  1714                                  
  1715                                  ;;     $if  c				; if lock conflicts occur - error      ;AC000;
  1716                                  
  1717                                  ;   now we must check what type of lock exists
  1718                                  ;   and the type of operation in progress.
  1719                                  
  1720                                  ;;	   cmp	al,write_op		;				       ;AN000;
  1721                                  
  1722                                  ;;	   $if	ne,and			; if NOT a write operation and	       ;AN000;
  1723                                  
  1724                                  ;;	   cmp	[si].rlr_type,rlr_lwr	;				       ;AN000;
  1725                                  
  1726                                  ;;	   $if	e			; if write locked (NOT all locked)     ;AN000;
  1727                                  
  1728                                  ;;	       clc			; then not true conflict - clear error ;AN000;
  1729                                  
  1730                                  ;;	   $else			; else it IS a valid conflict	       ;AC000;
  1731                                  
  1732                                  ;;	       stc			; true error - set error status
  1733                                  
  1734                                  ;;	   $endif			; endif - a valid conflict	       ;AC000;
  1735                                  
  1736                                  
  1737                                  ;;     $endif				; endif -  conflicts		       ;AC000;
  1738                                  
  1739 0000022C B82100                         mov  ax,error_lock_violation	; assume error
  1740                                  
  1741                                  ;  $endif				; endif - no need to check	       ;AC000;
  1742                                  D_$IF22:
  1743                                  
  1744                                  ;	exit
  1745                                  ;
  1746                                  ;	'C' and (ax) setup
  1747                                  
  1748 0000022F 1F                         POP	DS
  1749 00000230 59                         POP	CX
  1750 00000231 5F                         POP	DI
  1751 00000232 07                         POP	ES
  1752 00000233 E8(0000)                   LeaveCrit critShare
  1753                                  
  1754 00000236 C3                         ret					; exit
  1755                                  
  1756                                     EndProc Chk_Block
  1757                                  
  1758                                     BREAK <MFT_get - get an entry from the MFT>
  1759                                  
  1760                                  ;******************* START OF SPECIFICATIONS ***********************************
  1761                                  ;
  1762                                  ;	MFT_get - get an entry from the MFT
  1763                                  ;
  1764                                  ;	MFT_get is used to return information from the MFT.  System utilities
  1765                                  ;	use this capability to produce status displays.
  1766                                  ;
  1767                                  ;	MFT_get first locates the (BX)'th file in the list (no particular
  1768                                  ;		ordering is promised).	It returns that name and the UID of
  1769                                  ;		the (CX)'th SFT on that file and the number of locks on that
  1770                                  ;		file via that SFT.
  1771                                  ;
  1772                                  ;	ENTRY	DS:SI point to DPL which contains:
  1773                                  ;		(dBX) = zero-based file index
  1774                                  ;		(dCX) = zero-based SFT index
  1775                                  ;		(SS) = DOSGroup
  1776                                  ;	EXIT	'C' clear if no error
  1777                                  ;		  ES:DI buffer is filled in with BX'th file name
  1778                                  ;		  (BX) = user id of SFT
  1779                                  ;		  (CX) = # of locks via SFT
  1780                                  ;		'C' set if error
  1781                                  ;		  (ax) = error code
  1782                                  ;			    ('error_no_more_files' if either index is out
  1783                                  ;			     of range)
  1784                                  ;
  1785                                  ;******************* END OF SPECIFICATIONS *************************************
  1786                                  
  1787                                     Procedure MFT_get,NEAR
  1787          ******************       warning: proc MFT_get... [-w+user]
  1788                                  
  1789                                  ;  int 3
  1790 00000237 90                         nop
  1791 00000238 90                         nop
  1792                                  
  1793                                     ASSUME DS:NOTHING,ES:NOTHING
  1794                                  
  1795 00000239 E8(0000)                   EnterCrit critShare
  1796 0000023C 8B5C02                     MOV	BX,[SI + DPL_BX]
  1797 0000023F 8B4C04                     MOV	CX,[SI + DPL_CX]
  1798 00000242 1607                       Context ES
  1799 00000244 BF[0000]                   MOV	DI,OFFSET OpenBuf wrt DOSGROUP
  1800                                  
  1801 00000247 87D9                       xchg bx,cx				; (cx) = file index
  1802 00000249 0E                         push cs
  1803 0000024A 1F                         pop	ds
  1804                                  
  1805 0000024B BE[0000]                   Off	SI,mft				; (ds:si) = fwa of OFFSET MFT
  1806                                  
  1807                                  ;	scan forward until next name
  1808                                  
  1809 0000024E 803C00                  mget1: cmp byte [si + mft_flag],MFLG_FRE
  1810 00000251 7405                       jz	mget3				; is free space
  1811 00000253 7C24                       jl	mget7				; is END
  1812                                  
  1813                                  ;	have another name.  see if this satisfies caller
  1814                                  
  1815 00000255 E306                       jcxz mget4				; caller is happy
  1816 00000257 49                         dec	cx
  1817 00000258 037401                  mget3: add si,[si + mft_len]		; skip name record
  1818 0000025B EBF1                       JMP	SHORT mget1
  1819                                  
  1820                                  ;	we've located the file name.
  1821                                  ;
  1822                                  ;	(bx) = SFT index
  1823                                  ;	(DS:SI) = MFT entry
  1824                                  ;	(ES:DI) = address of caller's buffer
  1825                                  
  1826 0000025D 57                      mget4: push di
  1827 0000025E 56                         push si				; save table offset
  1828 0000025F 83C60C                     add	si,mft_name
  1829 00000262 AC                      mget5: lodsb
  1830 00000263 AA                         stosb				; copy name into caller's buffer
  1831 00000264 08C0                       or	al,al
  1832 00000266 75FA                       jnz	mget5
  1833 00000268 5E                         pop	si				; (DS:SI) = name record address
  1834 00000269 87D9                       xchg bx,cx				; (cx) = SFT chain count
  1835 0000026B C57C06                     lds	di,[si + mft_sptr]
  1836 0000026E E311                    mget6: jcxz mget8			; have reached the SFT we wanted
  1837 00000270 49                         dec	cx
  1838 00000271 C57D2B                     lds	di,[di + sf_chain]		; get next link
  1839 00000274 09FF                       or	di,di
  1840 00000276 75F6                       jnz	mget6				; follow chain some more
  1841 00000278 5F                         pop	di				; (es:di) = buffer address
  1842                                  
  1843                                  ;**	The file or SFT index was too large - return w/ error
  1844                                  
  1845 00000279 B81200                  mget7: mov ax,error_no_more_files
  1846 0000027C F9                         stc
  1847 0000027D E8(0000)                   LeaveCrit critShare
  1848                                  
  1849 00000280 C3                         ret
  1850                                  
  1851                                  ;**	We've got the SFT he wants.  Lets count the locks
  1852                                  ;
  1853                                  ;	(es:TOS) = buffer address
  1854                                  ;	(DS:DI) = address of SFT
  1855                                  ;	(si) = address of mft
  1856                                  
  1857 00000281 8B4505                  mget8: mov ax,[DI + sf_flags]
  1858 00000284 8CDA                       mov	dx,ds				; save segment
  1859 00000286 0E                         push cs
  1860 00000287 1F                         pop	ds
  1861 00000288 8B7404                     mov	si,[si + mft_lptr]		; (DS:SI) = Lock record address
  1862 0000028B 29C9                       sub	cx,cx				; clear counter
  1863                                  
  1864 0000028D 09F6                    mget9: or si,si
  1865 0000028F 740F                       jz	mget11				; no more
  1866 00000291 3B7C0A                     cmp	di,WORD PTR [si + rlr_sptr]
  1867 00000294 7506                       jnz	mget10
  1868 00000296 3B540C                     cmp	dx,word PTR [si + rlr_sptr + 2]
  1869 00000299 7501                       jnz	mget10
  1870 0000029B 41                         inc	cx
  1871 0000029C 8B34                    mget10: mov si,[si + rlr_next]
  1872 0000029E EBED                       JMP	SHORT mget9
  1873                                  
  1874                                  ;	Done counting locks.  return the info
  1875                                  ;
  1876                                  ;	(cx) = count of locks
  1877                                  ;	(es:TOS) = buffer address
  1878                                  
  1879 000002A0 8EDA                    mget11: mov ds,dx
  1880                                  SF_UID equ sf_UID	; NASM port equate
  1881 000002A2 8B5D2F                     mov	bx,[di + SF_UID]			; (bx) = UID
  1882 000002A5 5F                         pop	di
  1883 000002A6 F8                         clc
  1884 000002A7 E8(0000)                   LeaveCrit critShare
  1885                                  
  1886 000002AA C3                         ret
  1887                                  
  1888                                     EndProc MFT_get
  1889                                  
  1890                                     BREAK <ASC - Add SFT to Chain>
  1891                                  
  1892                                  ;******************* START OF SPECIFICATIONS ***********************************
  1893                                  ;
  1894                                  ;	ASC - Add SFT to Chain
  1895                                  ;
  1896                                  ;	ASC is called to add an SFT to the front of the chain.
  1897                                  ;
  1898                                  ;	ASC checks the file share mode bits on the other SFTs in the chain and
  1899                                  ;	reports a conflict.  The new SFT is NOT ADDED in the case of
  1900                                  ;	conflicts.
  1901                                  ;
  1902                                  ;	ENTRY	(BX) = FBA MFT name record
  1903                                  ;		(DS:SI) = SFT address
  1904                                  ;	EXIT	'C' clear if added
  1905                                  ;		    (ds:si) point to sft
  1906                                  ;		    (bx) offset of mft
  1907                                  ;		'C' set if conflict
  1908                                  ;		  (ax) = error code
  1909                                  ;	USES	ALL
  1910                                  ;
  1911                                  ;******************* END OF SPECIFICATIONS *************************************
  1912                                  
  1913                                     Procedure ASC,NEAR
  1913          ******************       warning: proc ASC... [-w+user]
  1914                                  
  1915 000002AB 837C3300                   cmp	word [si + sf_MFT],0
  1916 000002AF 753A                       jnz	asc9				; already on chain - internal error
  1917                                  
  1918                                  ;	The SFT looks good... lets see if there are any use conflicts
  1919                                  
  1920                                  ;	Message 1,<"Adding sft ">
  1921                                  
  1922 000002B1 36A1[0000]                 mov	ax,[ss:User_ID]			; place user information in SFT
  1923 000002B5 89442F                     mov	[si + sf_UID],ax			; do it before CUC (he checks UID)
  1924 000002B8 36A1[0000]                 mov	ax,[ss:Proc_ID]
  1925 000002BC 894431                     mov	[si + sf_PID],ax
  1926                                  
  1927 000002BF 2E803E[0000]01             cmp	byte [cs:skip_check],1
  1928                                  ;  $if	ne				;
  1929 000002C5 7403                       JE D_$IF24
  1930                                  
  1931 000002C7 E82301                         call CUC 			; check use conflicts
  1932                                  
  1933                                  ;  $endif
  1934                                  D_$IF24:
  1935                                  
  1936 000002CA 721E                       jc	asc8				; use conflicts - forget it
  1937                                  
  1938                                  ;	MessageNum   AX
  1939                                  
  1940                                  ;	MessageNum   AX
  1941                                  ;	Message 1,<" to ">
  1942                                  ;	MEssageNum  DS
  1943                                  ;	Message 1,<":">
  1944                                  ;	MessageNum  SI
  1945                                  ;	Message 1,<" ">
  1946                                  
  1947 000002CC 895C33                     mov	[si + sf_MFT],bx			; make SFT point to MFT
  1948                                  
  1949                                  ;	MessageNum  [si].sf_mft
  1950                                  ;	Message 1,<13,10>
  1951                                  
  1952 000002CF 8B4C02                     mov	cx,[si + sf_mode] 		; (cx) = open mode
  1953 000002D2 8CDA                       mov	dx,ds				; (dx:si) = SFT address
  1954 000002D4 0E                         push cs
  1955 000002D5 1F                         pop	ds				; (ds:bx) = MFT address
  1956                                  
  1957                                  ;
  1958                                  ;   Not special file and no previous sft found OR normal SFT.  We link it in
  1959                                  ;   at the head of the list.
  1960                                  ;
  1961                                  ;   (dx:si) point to sft
  1962                                  ;   (ds:bx) point to mft
  1963                                  ;
  1964 000002D6 C47F06                     les	di,[bx + mft_sptr]		; get first link
  1965 000002D9 897706                     mov	word ptr [bx + mft_sptr],si	; link in this sft
  1966 000002DC 895708                     mov	word ptr [bx + mft_sptr + 2],dx	; link in this sft
  1967 000002DF 8EDA                       mov	ds,dx
  1968 000002E1 897C2B                     mov	word ptr [si + sf_chain],di
  1969 000002E4 8C442D                     mov	word ptr [si + sf_chain + 2],es
  1970 000002E7 8EDA                    asc75: mov ds,dx			; point back to sft
  1971                                  
  1972 000002E9 F8                         clc
  1973 000002EA C3                      asc8: ret
  1974                                  
  1975                                  ;	the SFT is already in use... internal error
  1976                                  
  1977 000002EB 50                      asc9: push ax
  1978 000002EC B8[F202]                   off	ax,ascerr
  1979                                  INTERR equ interr	; NASM port label
  1980 000002EF E8(0000)                   call INTERR				; NEVER RETURNS
  1981 000002F2 4153433A2073667420-     ascerr db "ASC: sft already in use", 13, 10, 0
  1981 000002FB 616C72656164792069-
  1981 00000304 6E207573650D0A00   
  1982                                  
  1983                                     EndProc ASC
  1984                                  
  1985                                  
  1986                                     BREAK <BCS - Bulk Close of SFTs>
  1987                                  
  1988                                  ;******************* START OF SPECIFICATIONS ***********************************
  1989                                  ;
  1990                                  ;	BCS - Bulk Close of SFTs
  1991                                  ;
  1992                                  ;	BCS scans the MFT structures looking for SFTs that match a UID (and
  1993                                  ;	perhaps a PID).  The SFTs are closed.  The MFT name record is removed
  1994                                  ;	if all its SFTs are closed.
  1995                                  ;
  1996                                  ;	BCS is called with a PID and a PID MASK.  The SFT is closed if its UID
  1997                                  ;	matches the supplied UID AND (PID_ & PIDMASK) == PID_supplied
  1998                                  ;
  1999                                  ;	We walk the MFT structure closing all relevant SFT's. There is no
  2000                                  ;	need for special handling of 70 handles or FCBs.
  2001                                  ;
  2002                                  ;	Note that we call DOS_close to close the SFT; DOS_close in turn calls
  2003                                  ;	mftclose which may remove the SFT and even the MFT.  This means that
  2004                                  ;	the MFT may vanish as we are working on it.  Whenever we call
  2005                                  ;	DOS_close we'll know the next SFT and, if there is no next SFT we'll
  2006                                  ;	know the next MFT.  (If the MFT were released a pointer to the carcass
  2007                                  ;	is not of any help.  An MFT carcass cannot help find the next MFT
  2008                                  ;	record)
  2009                                  ;
  2010                                  ;	ENTRY	(AX) = UID to match
  2011                                  ;		(BX) = PID mask
  2012                                  ;		(DX) = PID value
  2013                                  ;	EXIT	'C' clear
  2014                                  ;	USES	ALL
  2015                                  ;
  2016                                  ;******************* END OF SPECIFICATIONS *************************************
  2017                                  
  2018                                     ASSUME SS:DOSGROUP
  2019                                  
  2020                                     Procedure BCS,NEAR
  2020          ******************       warning: proc BCS... [-w+user]
  2021                                  
  2022 0000030C 0E                         push cs
  2023 0000030D 1F                         pop	ds
  2024                                  
  2025 0000030E BE[0000]                   Off	SI,mft				; start at beginning of buffer
  2026                                  
  2027                                  ;	scan forward to the nearest name record (we may be at it now)
  2028                                  ;
  2029                                  ;	(DS:SI) = record pointer
  2030                                  
  2031 00000311 803C00                  bcs1: cmp byte [si + mft_flag],MFLG_FRE
  2032 00000314 7C07                       jl	bcs16				; at end of names, all done
  2033 00000316 7F08                       jg	bcs2				; have a name record
  2034                                  
  2035 00000318 037401                  bcs1$5: add si,[si + mft_len]		; skip record and loop
  2036 0000031B EBF4                       jmp	bcs1
  2037                                  
  2038 0000031D EB67                    bcs16: jmp bcs9
  2039 0000031F 90                      	nop	; identicalise
  2040                                  
  2041 00000320 C47C06                  bcs2: les di,[si + mft_sptr]		; got name record - get first SFT
  2042                                  ;	run down SFT chain
  2043                                  ;
  2044                                  ;	(es:di) = FBA next SFT
  2045                                  ;	(ds:si) = FBA name record
  2046                                  ;	(ax) = UID to match
  2047                                  ;	(bx) = PID mask
  2048                                  ;	(dx) = PID value
  2049                                  
  2050 00000323 09FF                    bcs3: or di,di
  2051 00000325 74F1                       jz	bcs1$5				; at end of SFT chain
  2052 00000327 263B452F                   cmp	ax,[es:di + sf_UID]
  2053 0000032B 750A                       jnz	bcs4				; not a match
  2054 0000032D 268B4D31                   mov	cx,[es:di + sf_PID]
  2055 00000331 21D9                       and	cx,bx				; apply mask
  2056 00000333 39D1                       cmp	cx,dx
  2057 00000335 7406                       jz	bcs51				; got a match
  2058                                  bcs4:
  2059 00000337 26C47D2B                   les	di,[es:di + sf_chain]
  2060 0000033B EBE6                       JMP	bcs3				; chain to next SFT
  2061                                  
  2062                                  
  2063                                  ;	We have an SFT to close
  2064                                  ;
  2065                                  ;	(es:di) = FBA SFT to be closed
  2066                                  ;
  2067                                  ;	(ds:si) = FBA name record
  2068                                  ;	(ax) = UID to match
  2069                                  ;	(bx) = PID mask
  2070                                  ;	(dx) = PID value
  2071                                  
  2072 0000033D 26C7050100              bcs51: mov word [es:di + sf_ref_count],1
  2073 00000342 50                         push ax
  2074 00000343 53                         push bx
  2075 00000344 52                         push dx				; save ID values (ax,bx,dx) and mask
  2076 00000345 1E                         push ds
  2077 00000346 56                         push si				; save name record address (ds:si)
  2078 00000347 268B752B                   mov	si,word ptr [es:di + sf_chain]
  2079 0000034B 09F6                       or	si,si
  2080 0000034D 750E                       jnz	bcs7				; isnt last sft, MFT will remain
  2081                                  
  2082                                  ;	yup, this is the last sft for this MFT, the MFT may evaporate.	we have
  2083                                  ;	to find the next one NOW, and remember it
  2084                                  
  2085 0000034F 5E                         pop	si				; undo saved name record address
  2086 00000350 1F                         pop	ds
  2087 00000351 037401                  bcs6: add si,[si + mft_len]		; go to next guy
  2088 00000354 803C00                     cmp	byte [si + mft_flag],MFLG_FRE
  2089 00000357 74F8                       jz	bcs6				; must be a non-free guy
  2090 00000359 1E                         push ds
  2091 0000035A 56                         push si				; resave our new next MFT
  2092 0000035B 29F6                       sub	si,si				; no next sft
  2093                                  
  2094                                  ;	Allright, we're ready to call the DOS.
  2095                                  ;
  2096                                  ;	(es:di)     = FBA sft to be closed
  2097                                  ;	((sp))	 = long address of current or next MFT
  2098                                  ;	((sp)+4) = PID value
  2099                                  ;	((sp)+6) = PID mask
  2100                                  ;	((sp)+8) = UID value
  2101                                  
  2102 0000035D 36893E[0000]            bcs7: mov WORD PTR [ss:ThisSFT],di
  2103 00000362 368C06[0200]               mov	WORD PTR [ss:ThisSFT+2],es
  2104 00000367 268E452D                   mov	es,word ptr [es:di + sf_chain + 2]
  2105 0000036B 0656                       SaveReg <es,si>
  2106 0000036D E8(0000)                   call CPS				; clear JFN
  2107 00000370 161F                       Context DS
  2108                                  
  2109                                  multDos equ MultDOS	; NASM port equate
  2110 00000372 B80112CD2F                 CallInstall DOS_Close,multDos,1
  2111                                  
  2112                                     ASSUME DS:NOTHING
  2113                                  
  2114 00000377 5F07                       RestoreReg <di,es>			; (es:DI) = offset of next sft
  2115 00000379 5E                         pop	si
  2116 0000037A 1F                         pop	ds				; (DS:SI) = fwa of current or next MFT
  2117 0000037B 5A                         pop	dx
  2118 0000037C 5B                         pop	bx
  2119 0000037D 58                         pop	ax
  2120 0000037E 09FF                       or	di,di
  2121 00000380 7502                       jnz	bcs85				; have more sft's
  2122 00000382 EB8D                       JMP	bcs1				; look at this new MFT
  2123 00000384 EB9D                    bcs85: jmp bcs3
  2124                                  
  2125                                  ;	All Done
  2126                                  
  2127 00000386 F8                      bcs9: clc
  2128                                  
  2129 00000387 C3                         ret
  2130                                  
  2131                                     EndProc BCS
  2132                                  
  2133                                     BREAK <CSL - Clear SFT Locks>
  2134                                  
  2135                                  ;******************* START OF SPECIFICATIONS ***********************************
  2136                                  ;
  2137                                  ;	CSL - Clear SFT Locks
  2138                                  ;
  2139                                  ;	CSL clears any locks associated with this SFT.
  2140                                  ;
  2141                                  ;	ENTRY	(ES:DI) = SFT address
  2142                                  ;	EXIT	(ES:DI) unchanged
  2143                                  ;	USES	All but ES,DI
  2144                                  ;
  2145                                  ;******************* END OF SPECIFICATIONS *************************************
  2146                                  
  2147                                     Procedure CSL,NEAR
  2147          ******************       warning: proc CSL... [-w+user]
  2148                                  
  2149 00000388 268B7533                   mov	si,[es:di + sf_MFT]
  2150 0000038C 0E                         push cs
  2151 0000038D 1F                         pop	ds
  2152 0000038E 8D5C04                     lea	bx,[si + mft_lptr]		; (DS:BX) = addr of lock ptr
  2153 00000391 8B37                       mov	si,[bx] 			; (DS:SI) = fba first lock record
  2154                                  
  2155                                  ;	scan the locks looking for belongers.
  2156                                  ;
  2157                                  ;	(es:di) = SFT address
  2158                                  ;	(ds:si) = this lock address
  2159                                  ;	(ds:bx) = address of link (offset value) to this lock (prev lock)
  2160                                  
  2161 00000393 09F6                    csl1: or si,si
  2162 00000395 7437                       jz	csl3				; done with lock list
  2163 00000397 3B7C0A                     cmp	di,word ptr [si + rlr_sptr]
  2164 0000039A 752C                       jnz	csl2				; not my lock
  2165 0000039C 8CC0                       mov	ax,es
  2166 0000039E 3B440C                     cmp	ax,word ptr [si + rlr_sptr + 2]
  2167 000003A1 7525                       jnz	csl2				; not my lock
  2168                                  ;
  2169                                  ; Make sure that the lock REALLY belongs to the correct process
  2170                                  ;
  2171 000003A3 36813E[0000]045D           cmp	word [ss:user_in_ax], (ServerCall << 8) + 4 ; only check if   ; @@01
  2172 000003AA 7509                       jnz	csl15				; process specific; @@01
  2173 000003AC 36A1[0000]                 mov	ax,[ss:Proc_ID]
  2174 000003B0 3B440E                     cmp	ax,[si + rlr_pid] 		; is process ID of lock = this PID?
  2175 000003B3 7513                       jnz	csl2				; nope, skip this lock
  2176                                  
  2177                                  ;	got a lock to remove
  2178                                  
  2179                                  csl15:
  2180 000003B5 8B14                       mov	dx,[si + rlr_next]
  2181 000003B7 8917                       mov	[bx],dx 			; link him out
  2182 000003B9 2EA1[0000]                 mov	ax,[cs:Frelock]
  2183 000003BD 8904                       mov	[si + rlr_next],ax
  2184 000003BF 2E8936[0000]               mov	[cs:Frelock],si
  2185 000003C4 89D6                       mov	si,dx				; (DS:SI) = next lock address
  2186 000003C6 EBCB                       JMP	SHORT csl1
  2187                                  
  2188                                     ERRNZ rlr_next			; lock is not ours... follow chain
  2189 000003C8 89F3                    csl2: mov bx,si
  2190 000003CA 8B34                       mov	si,[si + rlr_next]
  2191 000003CC EBC5                       JMP	SHORT csl1
  2192                                  
  2193                                  ;	All done
  2194                                  
  2195 000003CE C3                      csl3: ret
  2196                                  
  2197                                     EndProc CSL
  2198                                  
  2199                                     ASSUME DS:NOTHING
  2200                                  
  2201                                     BREAK <CUC - check usage conflicts>
  2202                                  
  2203                                  ;******************* START OF SPECIFICATIONS ***********************************
  2204                                  ;
  2205                                  ;	Use conflict table
  2206                                  ;
  2207                                  ;	Algorithm:
  2208                                  ;
  2209                                  ;		if ((newmode == COMPAT) or (oldmode == COMPAT))
  2210                                  ;			and (user ID's match)
  2211                                  ;		   then accept
  2212                                  ;		else
  2213                                  ;		for new and old mode, compute index of (SH*3)+ACC
  2214                                  ;		shift right table[new_index] by old_index+2;
  2215                                  ;			'C' set if FAIL
  2216                                  ;
  2217                                  ;	The bit in the old_index position indicates the success or failure.  0
  2218                                  ;	=> allow access, 1 => fail access
  2219                                  ;
  2220                                  ;******************* END OF SPECIFICATIONS *************************************
  2221                                  
  2222                                     PUBLIC CUCA
  2223                                  
  2224 000003CF FFFF                    CUCA: DW 0ffffh 			; Compat    Read
  2225 000003D1 FFFF                       DW	0ffffh				; Compat    Write
  2226 000003D3 FFFF                       DW	0ffffh				; Compat    Read/Write
  2227 000003D5 FFFF                       DW	0ffffh				; Deny R/W  Read
  2228 000003D7 FFFF                       DW	0ffffh				; Deny R/W  Write
  2229 000003D9 FFFF                       DW	0ffffh				; Deny R/W  Read/Write
  2230 000003DB 7FDF                       DW	0df7fh				; Deny W    Read
  2231 000003DD FFDB                       DW	0dbffh				; Deny W    Write
  2232 000003DF FFDF                       DW	0dfffh				; Deny W    Read/Write
  2233 000003E1 FFBE                       DW	0beffh				; Deny R    Read
  2234 000003E3 FFB7                       DW	0b7ffh				; Deny R    Write
  2235 000003E5 FFBF                       DW	0bfffh				; Deny R    Read/Write
  2236 000003E7 7F1C                       DW	01c7fh				; Deny None Read
  2237 000003E9 FF03                       DW	003ffh				; Deny None Write
  2238 000003EB FF1F                       DW	01fffh				; Deny None Read/Write
  2239                                  
  2240                                  ;					     4443 3322 2111 000
  2241                                  ;   Deny/Compat 			/    DDDD DDDD DDDD CCCx
  2242                                  ;   DenyRead			       /	R RR	RRR
  2243                                  ;   DenyWrite		  1st Access =< 	    WW WWWW
  2244                                  ;   AccessRead			       \     R RR  RR  RR R R R
  2245                                  ;   AccessWrite 			\    WW W W WW	WW  WW
  2246                                  ;   x					     1111 1111 1111 1111
  2247                                  ;   C  R    00				     1111 1111 1111 1111  ffff
  2248                                  ;   C	W   01				     1111 1111 1111 1111  ffff
  2249                                  ;   C  RW   02				     1111 1111 1111 1111  ffff
  2250                                  
  2251                                  ;   DRWR    10				     1111 1111 1111 1111  ffff
  2252                                  ;   DRW W   11				     1111 1111 1111 1111  ffff
  2253                                  ;   DRWRW   12				     1111 1111 1111 1111  ffff
  2254                                  ;   D WR    20				     1101 1111 0111 1111  df7f
  2255                                  
  2256                                  ;   D W W   21				     1101 1011 1111 1111  dbff
  2257                                  ;   D WRW   22				     1101 1111 1111 1111  dfff
  2258                                  ;   DR R    30				     1011 1110 1111 1111  beff
  2259                                  ;   DR	W   31				     1011 0111 1111 1111  b7ff
  2260                                  
  2261                                  ;   DR RW   32				     1011 1111 1111 1111  bfff
  2262                                  ;   D  R    40				     0001 1100 0111 1111  1c7f
  2263                                  ;   D	W   41				     0000 0011 1111 1111  03ff
  2264                                  ;   D  RW   42				     0001 1111 1111 1111  1fff
  2265                                  
  2266                                  ;   In order to allow the greatest number of accesses, compatability read mode
  2267                                  ;   is treated as deny-write read.  The other compatability modes are treated
  2268                                  ;   as deny-both.
  2269                                  
  2270                                  ;******************* START OF SPECIFICATIONS ***********************************
  2271                                  ;
  2272                                  ;	CUC - check usage conflicts
  2273                                  ;
  2274                                  ;	CUC is called to see if a would-be open would generate a share
  2275                                  ;	conflict with an existing open.  See CUCA for the algorithm and table
  2276                                  ;	format.
  2277                                  ;
  2278                                  ;	ENTRY	(BX) = FBA MFT name record
  2279                                  ;		(DS:SI) = SFT address
  2280                                  ;	EXIT	'C' clear if OK
  2281                                  ;		'C' set if conflict
  2282                                  ;		  (ax) = error code
  2283                                  ;	USES	ALL but arguments (BX, DS:SI)
  2284                                  ;
  2285                                  ;******************* END OF SPECIFICATIONS *************************************
  2286                                  
  2287                                     Procedure CUC,NEAR
  2287          ******************       warning: proc CUC... [-w+user]
  2288                                  
  2289 000003ED 1E                         push ds
  2290 000003EE 07                         pop	es
  2291 000003EF 89F7                       mov	di,si				; (es:di) = FBA SFT record
  2292                                  gom equ GOM	; NASM port label
  2293 000003F1 E86B00                     call gom				; get open mode
  2294 000003F4 88C5                       mov	ch,al
  2295 000003F6 80E5F0                     and	ch,sharing_mask 		; (ch) = new guy share
  2296 000003F9 7402                       jz	cuc0				; new guy is compatability mode
  2297 000003FB B5F0                       mov	ch,sharing_mask
  2298                                  csi equ CSI	; NASM port label
  2299 000003FD E84100                  cuc0: call csi				; compute share index
  2300 00000400 01C0                       add	ax,ax				; *2 for word index
  2301 00000402 96                         xchg ax,si				; (si) = share table index
  2302 00000403 0E                         push cs
  2303 00000404 1F                         pop	ds				; (ds:bx) = FBA MFT record
  2304 00000405 2E8B94[CF03]               mov	dx,WORD PTR [cs:CUCA + si]		; (dx) = share mask
  2305 0000040A C57706                     lds	si,[bx + mft_sptr]		; (ds:si) = first sft guy
  2306                                  
  2307                                  ;	ready to do access compares.
  2308                                  ;
  2309                                  ;	(ds:si) = address of next sft
  2310                                  ;	(es:di) = address of new  sft
  2311                                  ;	(dx) = share word from CUCA
  2312                                  ;	(cs:bx) = MFT offset
  2313                                  ;	(ch) = 0 if new SFT is compatibilty mode, else sharing_mask
  2314                                  
  2315 0000040D 09F6                    cuc1: or si,si
  2316 0000040F 742B                       jz	cuc9				; at end of chain, no problems
  2317 00000411 E84B00                     call gom				; if not FCB, then mode in al is good
  2318 00000414 88C4                       mov	ah,al
  2319 00000416 80E4F0                     and	ah,sharing_mask 		; (ah) = sharing mode
  2320 00000419 08EC                       or	ah,ch				; (ah) = 0 iff new and old is SH_COMP
  2321 0000041B 7509                       jnz	cuc2				; neither is SH_COMP
  2322                                  
  2323                                  ;	Both the old and the new guy are SH_COMP mode.	If the UIDs match,
  2324                                  ;	step onward.  If they don't match do normal share check.
  2325                                  
  2326 0000041D 268B6D2F                   mov	bp,[es:di + sf_UID]
  2327 00000421 3B6C2F                     cmp	bp,[si + sf_UID]
  2328 00000424 740D                       jz	cuc20				; equal => next sft to check
  2329                                  
  2330 00000426 E81800                  cuc2: call csi				; compute the share index
  2331 00000429 40                         inc	ax
  2332 0000042A 40                         inc	ax
  2333 0000042B 86C1                       xchg al,cl				; (cl) = shift count
  2334 0000042D 89D0                       mov	ax,dx
  2335 0000042F D3F8                       sar	ax,cl				; select the bit
  2336 00000431 7205                       jc	cuc8				; a conflict!
  2337                                  cuc20:
  2338 00000433 C5742B                     lds	si,[si + sf_chain]
  2339 00000436 EBD5                       JMP	cuc1				; chain to next SFT and try again
  2340                                  
  2341                                  ;	Have a share conflict
  2342                                  
  2343 00000438 B82000                  cuc8: mov ax,error_sharing_violation	; assume share conflict
  2344 0000043B F9                         stc
  2345                                  
  2346                                  ;	done with compare.  Restore regs and return
  2347                                  ;
  2348                                  ;	'C' set as appropriate
  2349                                  ;	(es:di) = new SFT address
  2350                                  ;	(ax) set as appropriate
  2351                                  ;	(bx) = MFT offset
  2352                                  
  2353 0000043C 06                      cuc9: push es
  2354 0000043D 1F                         pop	ds
  2355 0000043E 89FE                       mov	si,di
  2356                                  
  2357 00000440 C3                         ret
  2358                                  
  2359                                     EndProc CUC
  2360                                  
  2361                                     BREAK <csi - compute share index>
  2362                                  
  2363                                  ;******************* START OF SPECIFICATIONS ***********************************
  2364                                  ;
  2365                                  ;	csi - compute share index
  2366                                  ;
  2367                                  ;
  2368                                  ;	If the mode byte has a leading 7 then it is interpreted as a 0
  2369                                  ;	csi turns a mode byte into an index from 0 to 14:
  2370                                  ;
  2371                                  ;		(share index)*3 + (access index)
  2372                                  ;
  2373                                  ;	ENTRY	(al) = mode byte
  2374                                  ;	EXIT	(ax) = index
  2375                                  ;	USES	AX, CL
  2376                                  ;
  2377                                  ;******************* END OF SPECIFICATIONS *************************************
  2378                                  
  2379                                     Procedure CSI,NEAR
  2379          ******************       warning: proc CSI... [-w+user]
  2380                                  
  2381 00000441 88C4                       mov	ah,al
  2382 00000443 80E40F                     and	ah,access_mask			; (ah) = access bits
  2383 00000446 24F0                       and	al,sharing_mask 		; (al) = share bites
  2384                                     ERRNZ sharing_mask-0F0h
  2385 00000448 3C70                       cmp	al,sharing_net_FCB
  2386 0000044A 7502                       jnz	csi1
  2387 0000044C 30C0                       xor	al,al
  2388                                  csi1:
  2389 0000044E D0E8                       shr	al,1
  2390 00000450 D0E8                       shr	al,1
  2391 00000452 D0E8                       shr	al,1
  2392 00000454 88C1                       mov	cl,al				; (cl) = SHVAL*2
  2393 00000456 D0E8                       shr	al,1
  2394 00000458 00C8                       add	al,cl				; (al) = SHVAL*3
  2395 0000045A 00E0                       add	al,ah				; (al) = SH*3 + ACC
  2396 0000045C 28E4                       sub	ah,ah
  2397                                  
  2398 0000045E C3                         ret
  2399                                  
  2400                                     EndProc CSI
  2401                                  
  2402                                     Break <GOM - get open mode>
  2403                                  
  2404                                  ;******************* START OF SPECIFICATIONS ***********************************
  2405                                  ;
  2406                                  ;	GOM - get open mode
  2407                                  ;
  2408                                  ;   Find the correct open mode given the encoded sf_mode.  Note that files
  2409                                  ;   marked READ-ONLY and are opened in compatability read-only are treated as
  2410                                  ;   deny-write read-only.  FCB opens are sharing_compat open_for_both and
  2411                                  ;   net FCB opens are sharing_compat
  2412                                  ;
  2413                                  ;	Entry:	    (DS:SI) points to SFT
  2414                                  ;   Exit:	(AL) has correct mode
  2415                                  ;   Uses:	(AX)
  2416                                  ;******************* END OF SPECIFICATIONS *************************************
  2417                                  
  2418                                     Procedure GOM,NEAR
  2418          ******************       warning: proc GOM... [-w+user]
  2419                                  
  2420 0000045F 8B4402                     mov	ax,[si + sf_mode]
  2421                                  sf_IsFCB equ sf_isfcb	; NASM port equate
  2422 00000462 A90080                     TEST AX,sf_IsFCB
  2423 00000465 7402                       jz	gom1				; if not FCB, then mode in al is good
  2424 00000467 B002                       mov	al,sharing_compat+open_for_both
  2425                                  gom1:
  2426 00000469 88C4                       mov	ah,al
  2427 0000046B 80E4F0                     and	ah,sharing_mask
  2428 0000046E 80FC70                     cmp	ah,sharing_net_FCB		; is sharing from net FCB?
  2429 00000471 7504                       jnz	gom2				; no, got good mode
  2430 00000473 240F                       and	al,access_mask			; yes, convert to compat mode sharing
  2431 00000475 0C00                       or	al,sharing_compat
  2432                                  ;
  2433                                  ; The sharing mode and access mode in AL is now correct for the file.  See if
  2434                                  ; mode is compatability.  If so and file is read-only, convert access mode to
  2435                                  ; deny-write read.
  2436                                  ;
  2437                                  gom2:
  2438 00000477 88C4                       mov	ah,al
  2439 00000479 80E4F0                     and	ah,sharing_mask
  2440 0000047C 7401C3                     retnz				; not compatability, return.
  2441 0000047F F6440401                   test byte [si + sf_attr],attr_read_only
  2442 00000483 74F9                       retz 				; not read-only
  2443 00000485 B020                       mov	al,sharing_deny_write + open_for_read
  2444                                  
  2445 00000487 C3                         ret
  2446                                  
  2447                                     EndProc GOM
