1 Title Share_1
- IBM CONFIDENTIAL
5 ; Label: "The DOS SHARE Utility"
6 ; "Version 4.00 (C) Copyright 1988 Microsoft"
7 ; "Licenced Material - Program Property of Microsoft"
9 ;******************* END OF SPECIFICATIONS *************************************
11 extrn fnm
:near, rsc
:near, rmn
:near, cps
:near, ofl
:near, sle
:near, interr
:near
22 AsmVars
<IBM
, Installed
>
24 Installed
= TRUE
; for installed version
30 mov si,OFFSET DOSGROUP
:val
39 ; if we are installed, then define the base code segment of the sharer first
42 Share
SEGMENT PARA
PUBLIC 'SHARE'
44 ; include the rest of the segment definitions for normal msdos
45 ; We CANNOT include dosseg because start is not declared para in that file
49 START
SEGMENT PARA
PUBLIC 'START'
52 CONSTANTS
SEGMENT WORD PUBLIC 'CONST'
55 DATA SEGMENT WORD PUBLIC 'DATA'
58 TABLE
SEGMENT BYTE PUBLIC 'TABLE'
61 CODE SEGMENT BYTE PUBLIC 'CODE'
64 LAST
SEGMENT PARA
PUBLIC 'LAST'
67 DOSGROUP GROUP START
,CONSTANTS
,DATA,TABLE
,CODE,LAST
72 DATA SEGMENT WORD PUBLIC 'DATA'
73 Extrn ThisSFT
:DWORD ; pointer to SFT entry
87 ; if we are not installed, then the code here is just part of the normal
88 ; MSDOS code segment otherwise, define our own code segment
92 CODE SEGMENT BYTE PUBLIC 'CODE'
93 ASSUME
SS:DOSGROUP
,CS:DOSGROUP
95 Share
SEGMENT PARA
PUBLIC 'SHARE'
96 ASSUME
SS:DOSGROUP
,CS:SHARE
100 extrn skip_check
:BYTE
104 PUBLIC FreLock
,Serial
107 Frelock
DW ?
; FWA of lock free list
109 Frelock
DW OFFSET DOSGROUP
:lck8
; FWA of lock free list
111 Serial
DW 0 ; serial number
112 DS_Org dw 0 ;an000;DS on entry to routine
128 BREAK <Sharer
- MultiProcess
File Sharer
>
130 ;******************* START OF SPECIFICATIONS ***********************************
132 ; MSDOS MFT Functions
134 ; The Master File Table (MFT) associates the cannonicalized pathnames,
135 ; lock records and SFTs for all files open on this machine.
137 ; These functions are supplied to maintain the MFT and extract
138 ; information from it. All MFT access should be via these routines so
139 ; that the MFT structure can remain flexible.
141 ;******************* END OF SPECIFICATIONS *************************************
143 BREAK <Mft_enter
- Make an MFT
entry and check access
>
145 ;******************* START OF SPECIFICATIONS ***********************************
147 ; mft_enter - make an entry in the MFT
149 ; mft_enter is called to make an entry in the MFT.
150 ; mft_enter checks for a file sharing conflict:
152 ; A new MFT entry is created, or the existing one updated,
155 ; The existing MFT is left alone. Note that if we had to
156 ; create a new MFT there cannot be, by definition, sharing
158 ; If no conflict has been discovered, the SFT list for the file is
159 ; checked for one that matches the following conditions:
164 ; If mode&sfIsFCB and userids match and process ids match then
167 ; ENTRY ThisSFT points to an SFT structure. The sf_mode field
168 ; contains the desired sharing mode.
169 ; WFP_Start is an offset from DOSGroup of the full pathname for
171 ; User_ID = 16-bit user id of issuer
172 ; Proc_ID = 16-bit process id of issuer
173 ; (DS) = (SS) = DOSGroup
174 ; EXIT 'C' clear if no error'
179 ;******************* END OF SPECIFICATIONS *************************************
181 Procedure mft_enter
,NEAR
189 DOSAssume
SS <DS>,"MFT_Enter entry"
190 ASSUME
ES:NOTHING
,SS:DOSGROUP
193 ; find or make a name record
195 mov si,WFP_Start
; (DS:SI) = FBA of file name
196 mov al,1 ; allow creation of MFT entry
201 call FNM
; find or create name in MFT
203 mov ax,error_sharing_buffer_exceeded
204 jc ent9
; not enough space
206 ; (bx) = fwa name record
209 call ASC
; try to add to chain
211 ; As noted above, we don't have to worry about an "empty" name record
212 ; being left if ASC refuses to add the SFT - ASC cannot refuse if we had
213 ; just created the MFT...
217 ; 'C' and (Ax) setup appropriately
227 BREAK <MftClose
- Close
out an MFT for given SFT
>
229 ;******************* START OF SPECIFICATIONS ***********************************
235 ; MFTclose removes the SFT entry from the MFT structure. If this was
236 ; the last SFT for the particular file the file's entry is also removed
237 ; from the MFT structure. If the sharer is installed after some
238 ; processing has been done, the MFT field of the SFTs will be 0; we must
241 ; If the sft indicates FCB, we do nothing special. The SFT behaves
242 ; EXACTLY like a normal handle.
244 ; If the sft indicates mode 70 then we do nothing special. These are
247 ; Note that we always care about the SFT refcount. A refcount of 1
248 ; means that the SFT is going idle and that we need to remove the sft
251 ; ENTRY (ES:DI) points to an SFT structure
252 ; (DS) = (SS) = DOSGroup
254 ; USES ALL but DS, ES:DI
256 ;******************* END OF SPECIFICATIONS *************************************
258 Procedure MFTclose
,NEAR
266 DOSAssume
SS,<DS>,"MFTClose entry"
268 mov ax,es:[di].sf_MFT
270 fmt TypShare
,LevShEntry
,<"MFTClose by $x:$x of $x:$x ($x)\n">,<User_ID
,Proc_id
,ES,DI,AX>
273 jz mcl10
; No entry for it, ignore (carry clear)
277 ;;;call CSL ; clear SFT locks ;AC008;
281 mov ax,es:[di].sf_ref_count
; (ax) = ref count
283 ; We need to release information in one of two spots. First, when the SFT has
284 ; a ref count of 0. Here, there are no more referents and, thus, no sharing
285 ; record need be kept. Second, the ref count may be -1 indicating that the
286 ; sft is being kept but that the sharing information is no longer needed.
287 ; This occurs in creates of existing files, where we verify the allowed
288 ; access, truncate the file and regain the access. If the truncation
289 ; generates an error, we do NOT want to have the access locked down.
294 jz mcl85
; ref count is 0 - don't dechain
295 inc ax ; -1 + 1 = 0. Busy sft.
298 call CSL
; clear SFT locks ;AC008;
299 call RSC
; remove sft from chain
300 jnz mcl9
; not the last sft for this name
301 call RMN
; remove name record
303 pop di ; restore regs for exit
313 BREAK <MftClU
- Close
out all MFTs for given UID
>
315 ;******************* START OF SPECIFICATIONS ***********************************
321 ; MFTcloseM removes all entrys for user UID from the MFT structure. We
322 ; walk the MFT structure closing all relevant SFT's for the user.
323 ; We do it the dumb way, iterating closes until the SF ref count is
326 ; ENTRY User_ID = 16-bit user id of issuer
331 ;******************* END OF SPECIFICATIONS *************************************
333 Procedure MFTclU
,NEAR
339 ASSUME
DS:NOTHING
,ES:NOTHING
,SS:DOSGROUP
344 fmt TypShare
,LevShEntry
,<"\nCloseUser $x\n">,<AX>
346 sub bx,bx ; insensitive to PID
348 invoke BCS
; bulk close the SFTs
353 BREAK <MftCloseP
- Close
out all MFTs for given UID
/PID
>
355 ;******************* START OF SPECIFICATIONS ***********************************
359 ; MFTcloseP(PID, UID)
361 ; MFTcloseP removes all entrys for process PID on machine MID from the
362 ; MFT structure. We walk the MFT structure closing all relevant
363 ; SFT's. Do it the dumb way by iterating closes until the SFTs
366 ; ENTRY (SS) = DOSGROUP
367 ; User_ID = 16-bit user id of issuer
368 ; Proc_ID = 16-bit process id of issuer
372 ;******************* END OF SPECIFICATIONS *************************************
374 Procedure MFTcloseP
,NEAR
380 ASSUME
DS:NOTHING
,ES:NOTHING
,SS:DOSGROUP
387 fmt TypShare
,LevShEntry
,<"\nClose UID/PID $x:$x\n">,<AX,DX>
389 call BCS
; Bulk close the SFTs
396 BREAK <MftCloN
- Close
file by name
>
398 ;******************* START OF SPECIFICATIONS ***********************************
404 ; MFTcloseN removes all entrys for the given file from the MFT
407 ; NOTE: this function is used infrequently and need not be fast.
408 ; (although for typical use it's not all that slow...)
410 ; ENTRY DS:SI point to dpl.
412 ; EXIT 'C' clear if no error
414 ; AX = error_path_not_found if not currently open
417 ;******************* END OF SPECIFICATIONS *************************************
419 Procedure MFTcloN
,NEAR
425 ASSUME
SS:DOSGROUP
,ES:NOTHING
,DS:NOTHING
430 mov si,dx ; (DS:SI) = fwa name
431 sub al,al ; don't create if not found
434 call FNM
; find name in MFT
435 mov ax,error_path_not_found
; assume error
436 jc mclo9
; not found exit
438 ; Name was found. Lets yank the SFT entrys one at a time.
440 mclo1: les di,[bx].mft_sptr
; (ES:DI) = SFT address
441 mov WORD PTR ThisSFT
,di
442 mov WORD PTR ThisSFT
+2,es ; point to SFT
443 cmp es:[di].sf_ref_count
,1
450 MOV AX,(multDOS
SHL 8) + 1
463 sub al,al ; don't create an entry
464 call FNM
; find the name gain
465 jnc mclo1
; got still more
468 ; exit. 'C' and (ax) setup
470 ; (TOS+2:TOS) = address of ASCIZ string
472 mclo9: pop si ; clean stack
480 BREAK <Set_Mult_Block
- Try to set multiple locks
>
482 ;******************* START OF SPECIFICATIONS ***********************************
484 ; NAME: Set_Mult_Block - Set Multiple Block Locks
486 ; FUNCTION: Set_Mult_Block sets a lock on 1 or more specified ranges
487 ; of a file. An error is returned if any lock range conflicts
488 ; with another. Ranges of Locks are cleared via Clr_Mult_Block.
490 ; In DOS 3.3 only one lock range could be set at a time using
491 ; Set_Block. For DOS 4.00 this routine will replace Set_Block
492 ; in the jump table and will make repeated calls to Set_Block
493 ; in order to process 1 or more lock ranges.
495 ; NOTE: - This is an all new interface to IBMDOS
497 ; INPUT: (AL) = 0 - lock all
499 ; (CX) = the number of lock ranges
500 ; (DS:DX) = pointer to the range list
501 ; (ES:DI) = SFT address
502 ; User_ID = 16-bit user id of issuer
503 ; Proc_ID = 16-bit process id of issuer
506 ; OUTPUT: Lock records filled in for all blocks specified
508 ; REGISTERS USED: ALL but DS
511 ; LINKAGE: IBMDOS Jump Table
513 ; EXTERNAL Invoke: Load_Regs, Set_Block, Clr_Block
516 ; NORMAL 'C' clear if no error
519 ; ERROR 'C' set if error
520 ; EXIT: (ax) = error code
521 ; ('error_lock_violation' if conflicting locks)
523 ; CHANGE 04/15/87 - First release
526 ;******************* END OF SPECIFICATIONS *************************************
527 ;******************+ START OF PSEUDOCODE +**************************************
529 ; START Set_Mult_Block
531 ; count = start_count
532 ; search till count = 0
536 ; clear_count = start_count - current_count
537 ; loop till clear_count = 0
545 ; set successful status
554 ;******************+ END OF PSEUDOCODE +**************************************
556 Procedure Set_Mult_Block
,NEAR
565 ; mov ax,word ptr ds:[bx] ;ICE
566 ; mov word ptr ds:[bx],ax ;ICE
574 EnterCrit critShare
; ;AN000;
576 ASSUME
ES:NOTHING
,DS:NOTHING
; ;AN000;
579 ; WE HAVE: (from IBMDOS) | WE NEED: (for Set_Block)
581 ; (AL) = 0 - lock all | (BX) = 0 lock all operations
582 ; = 80- lock write | = 1 lock write operations
583 ; (CX) = the number of lock ranges | (CX:DX) = offset of area
584 ; (DS:DX) = pointer to the range list | (SI:AX) = length of area
585 ; (ES:DI) = SFT address | (ES:DI) = SFT address
591 mov DS_Org
,ds ;an000;save entry DS
594 CMP CX,01h ;DO WE HAVE A COUNT? ;AN000;
596 ;; $if ae ; if the count was valid ;AN000;
597 ; $if e ; if the count was valid ;AC006;
600 ;; PUSH CX ; count = start_count ;AN000;
601 ;; PUSH DX ; save pointer to range list ;AN000;
602 MOV BP,DX ; save current index into list ;AN000;
603 ;; AND AX,0080H ; clear high byte and be sure low is ;AN000;
605 ;; ROL AL,1 ; move high bit to bit 0
606 ;; MOV BX,AX ; SET UP TYPE OF LOCK ;AN000;
608 ;; $do ; loop till count = 0 ;AN000;
609 ;; cmp cx,00 ;an000;see if at end
610 ;; $leave e ;an000;exit if at end
611 ;; push cx ;an000;save cx - our counter
612 ;; push di ;an000;save di - our SFT pointer
613 call load_regs
;an000;load the registers for call
615 call set_block
;an000;set the lock block
616 ;; pop di ;an000;restore our SFT pointer
617 ;; pop cx ;an000;restore cx - our counter
618 ;; $leave c ;an000;on error exit loop
619 ;; dec cx ;an000;decrease counter
620 ;; $enddo ;an000;end loop
622 ;; $if c ;an000;if an error occurred
623 ;; pop dx ;an000;restore range list pointer
624 ;; pop ax ;an000;obtain original count
625 ;; sub ax,cx ;an000;determine how many locks set
626 ;; mov cx,ax ;an000;set the loop counter with count
627 ;; mov bp,dx ;an000;set bp to point to range list
628 ;; $do ;an000;while cx not = 0
629 ;; cmp cx,00 ;an000;at end?
630 ;; $leave e ;an000;yes, exit
631 ;; push cx ;an000;save cx - our counter
632 ;; push di ;an000;save di - our SFT pointer
633 ;; call load_regs ;an000;load the registers for call
635 ;; call clr_block ;an000;clear the locks
636 ;; pop di ;an000;restore our SFT pointer
637 ;; pop cx ;an000;restore cx - our counter
638 ;; $leave c ;an000;on error exit
639 ;; dec cx ;an000;decrease counter
641 ;; stc ;an000;signal an error occurred
642 ;; $else ;an000;no error occurred in locking
643 ;; pop ax ;an000;clear off the stack
644 ;; pop ax ;an000; to balance it
645 ;; clc ;an000;signal no error occurred
647 ; $else ;an000;cx was 0 - this is an error
650 stc ;an000;signal an error occurred
654 ; $if c ; if there was an error ;AN000;
656 MOV AX,error_lock_violation
; load the return code ;AN000;
657 ; $endif ; endif there was an error ;AN000;
660 LeaveCrit critShare
; ;AN000;
662 ret ; return - all set ;AN000;
664 EndProc Set_Mult_Block
666 BREAK <Load_Regs
- Load Registers for ?_Block
call>
668 ;******************* START OF SPECIFICATIONS ***********************************
670 ; NAME: Load_Regs - Load Registers for ?_Block calls
672 ; FUNCTION: This subroutine loads the High and Low Offsets and the
673 ; High and Low lengths for Lock ranges from the Range List.
675 ; INPUT: (DS_Org:PB) - Range list entry to be loaded
677 ; OUTPUT: (DX) - Low Offset
682 ; REGISTERS USED: AX CX DX BP SI
685 ; LINKAGE: Called by: Set_Mult_Block, Clr_Mult_Block
696 ; CHANGE 04/15/87 - first release
699 ;******************* END OF SPECIFICATIONS *************************************
700 ;******************+ START OF PSEUDOCODE +**************************************
704 ; recover index into range list
705 ; advance pointer to next entry
706 ; load DX - Low Offset
707 ; load CX - High Offset
708 ; load AX - Low Length
709 ; load SI - High Length
714 ;******************+ END OF PSEUDOCODE +**************************************
716 Procedure Load_Regs
,NEAR
718 push ds ; save our DS ;an000;
719 mov ds,DS_Org
; get range list segment ;an000;
720 mov si,bp ; recover pointer ;AN000;
721 ADD BP,08h ; move to next entry in list ;AN000;
722 MOV DX,[SI] ; low position ;AN000;
723 MOV CX,[SI+2] ; high position ;AN000;
724 MOV AX,[SI+4] ; low length ;AN000;
725 MOV SI,[SI+6] ; high length ;AN000;
726 pop ds ; restore DS ;an000;
732 BREAK <Clr_Mult_Block
- Try to clear multiple locks
>
734 ;******************* START OF SPECIFICATIONS ***********************************
736 ; NAME: Clr_Mult_Block - Clear Multiple Block Locks
738 ; FUNCTION: Clr_Mult_Block removes the locks on 1 or more specified
739 ; ranges of a file. An error is returned if any lock range
740 ; does not exactly match. Ranges of Locks are set via
743 ; In DOS 3.3 only one lock range could be cleared at a time
744 ; using Clr_Block. For DOS 4.00 this routine will replace
745 ; Clr_Block in the jump table and will make repeated calls
746 ; to Set_Block in order to process 1 or more lock ranges.
748 ; NOTE: - This is an all new interface to IBMDOS
749 ; - an unlock all 'lock all' request will unlock both
750 ; 'lock all' and 'lock write'.
751 ; - an unlock all 'lock write' request will not unlock
752 ; 'lock all's. It will only unlock 'lock write's.
753 ; (if you can understand the above statement,
754 ; understanding the code will be easy!)
756 ; INPUT: (AL) = 0 - lock all
758 ; (CX) = the number of lock ranges - NB: all if -1 ***
759 ; (DS:DX) = pointer to the range list
760 ; (ES:DI) = SFT address
761 ; User_ID = 16-bit user id of issuer
762 ; Proc_ID = 16-bit process id of issuer
765 ; OUTPUT: Lock records filled in for all blocks specified
767 ; REGISTERS USED: ALL but DS
770 ; LINKAGE: IBMDOS Jump Table
772 ; EXTERNAL Invoke: Load_Regs, Set_Block, Clr_Block, Clr_List
775 ; NORMAL 'C' clear if no error
778 ; ERROR 'C' set if error
779 ; EXIT: (ax) = error code
780 ; ('error_lock_violation' if conflicting locks)
782 ; CHANGE 04/15/87 - First release
785 ;******************* END OF SPECIFICATIONS *************************************
786 ;******************+ START OF PSEUDOCODE +**************************************
788 ; START Clr_Mult_Block
790 ; if count is valid and
791 ; if file (SFT) is 'shared' then
794 ; loop till all RLR cleared
795 ; if PROC_ID matches and
797 ; if SFT matches then
798 ; if ulocking lock_all or
799 ; if this RLR is lock_write
808 ; set successful status
820 ;******************+ END OF PSEUDOCODE +**************************************
822 Procedure clr_mult_block
,NEAR
834 ; mov ax,word ptr ds:[bx] ;ICE
835 ; mov word ptr ds:[bx],ax ;ICE
841 EnterCrit critShare
; ;AN000;
843 ASSUME
ES:NOTHING
,DS:NOTHING
; ;AN000;
849 mov DS_Org
,DS ;an000;save entry DS
853 CMP CX,01h ; do we have a count? ;AN000;
854 ;; $IF AE,AND ; IF A VALID COUNT
855 ; $IF E,AND ; IF A VALID COUNT ;AC006;
857 cmp es:[di].sf_mft
,0 ; is this SFT shared? ;AN000;
858 ; $IF NE ; AND IF FILE IS 'SHARED' THEN
861 ; WE HAVE: (from IBMDOS) | WE NEED:
863 ; (AL) = 0 - lock all | (AX) = 0 lock all operations
864 ; = 80- lock write | = 1 lock write operations
865 ; (CX) = - 1 (unlock all locks) | (DS) = CS
866 ; | (DS:DI) = previous RLR
867 ; | (DS:SI) = current RLR
868 ; (ES:DI) = current SFT |
870 ;; and ax,0080h ;be sure it is set right (mask 80 bit) ;AC002;
872 ;; rol al,1 ;put high bit in bit 0 ;AC002;
874 ;; CMP CX,-1h ; ;AN000;
875 ;; $IF E ; IF unlock all locks then ;AN000;
879 ;; mov cx,di ; ES:CX is the SFT ;AN004;
883 ;; mov si,es:[di].sf_mft ; DS:SI points to MFT ;AN000;
885 ;; lea di,[si].mft_lptr ; DS:DI = addr of ptr to lock record ;AN000;
886 ;; mov si,[di] ; DS:SI = address of 1st lock record ;AN000;
888 ;; $DO ; loop through the RLR's ;AN000;
890 ; DS:DI = points to previous RLR or MFT if no RLR.
891 ; DS:SI = points to current RLR
892 ; ES:CX = SFT address
895 ;; and si,si ; are we at the end of the chain? ;AN000;
896 ;; $LEAVE Z ; we'er done with CF = 0 ;AN000;
898 ;; mov bp,[si].rlr_pid ; get PROC_ID ;AN000;
899 ;; cmp bp,PROC_ID ; is it ours? ;AN000;
900 ;; $IF E,AND ; ;AN000;
901 ;; mov bp,es ; ;AN000;
902 ;; cmp bp,WORD PTR [si].rlr_sptr+2 ; ;AC004;
903 ;; $IF E,AND ; ;AN000;
904 ;; cmp cx,WORD PTR [si].rlr_sptr ; ;AC004;
905 ;; mov si,[di] ; restore pointer to current (using ;AN000;
907 ;; $IF E ; if it is ours ;AN000;
909 ; this is it. its OURS !
911 ;; cmp ax,lock_all ; ;AN000;
913 ;; $IF E,OR ; if unlocking all or ;AN000;
915 ;; mov bp,[si].rlr_type ; get lock type ;AN000;
916 ;; cmp bp,rlr_lall ; is it lock all? ;AN000;
918 ;; $IF NE ; if not a LOCK ALL lock ;AN000;
920 ; remove the RLR from the chain
922 ;; mov bx,[si].rlr_next ; get the pointer to the next RLR ;AN000;
923 ;; mov [di],bx ; install it in the last ;AN000;
925 ; put defunct lock record on the free chain
927 ;; mov bx,Frelock ; ;AN000;
928 ;; mov [si].rlr_next,bx ; ;AN000;
929 ;; mov Frelock,si ; ;AN000;
930 ;; mov si,di ; back up to last ;AN000;
932 ;; $ENDIF ; should we unlock it ;AN000;
934 ;; $ENDIF ; it was ours! ;AN000;
936 ; advance to next RLR
938 ;; mov di,si ; load address of next RLR ;AN000;
939 ;; mov si,[di] ; update pointer to next RLR ;AN000;
941 ;; $ENDDO ; loop back to the start ;AN000;
943 ;; $ELSE ; else, its a LIST ! ;AN000;
947 ; WE HAVE: (from IBMDOS) | WE NEED: (for Clr_Block)
949 ; (AX) = 0 - lock all | (BX) = 0 lock all operations
950 ; = 1 - lock write | = 1 lock write operations
951 ; (CX) = the number of lock ranges | (CX:DX) = offset of area
952 ; (DS:DX) = pointer to the range list | (SI:AX) = length of area
953 ; (ES:DI) = SFT address | (ES:DI) = SFT address
955 ;; PUSH CX ; count = start_count ;AN000;
956 ;; PUSH DX ; save pointer to range list ;AN000;
957 MOV BP,DX ; save current index into list ;AN000;
958 ;; MOV BX,AX ; SET UP TYPE OF LOCK ;AN000;
960 call Clr_List
; call Clr_List to process the list ;AN000;
970 ; $ENDIF ; VALID/INVALID ;AN000;
973 ; $IF C ; if carry is set ;AN000;
975 MOV AX,error_lock_violation
; load error condition ;AN000;
976 ; $ENDIF ; carry not set ;AN000;
979 LeaveCrit critShare
; ;AN000;
981 ret ; return - all set ;AN000;
983 EndProc clr_mult_block
985 BREAK <Clr_List
- Clear a list of user specified locks
>
987 ;******************* START OF SPECIFICATIONS ***********************************
989 ; NAME: Clr_List - Clear a list of user specified locks
991 ; FUNCTION: Clr_List makes multiple calls to Clr_Block to clear
992 ; multiple lock ranges of a file. An error is returned
993 ; if any lock range does not exactly match. Ranges of
994 ; Locks are then set via Set_Mult_Block.
997 ; INPUT: (BX) = 0 lock all operations
998 ; = 1 lock write operations
999 ; (CX:DX) = offset of area
1000 ; (SI:AX) = length of area
1001 ; (ES:DI) = SFT address
1002 ; (SS:SP+2)= original index \ see FRAME struc
1003 ; (SS:SP+4)= original count /
1005 ; OUTPUT: Lock records removed for all blocks specified
1006 ; Stack cleard on return
1008 ; REGISTERS USED: ALL but DS
1011 ; LINKAGE: IBMDOS Jump Table
1013 ; EXTERNAL Invoke: Load_Regs, Set_Block, Clr_Block
1016 ; NORMAL 'C' clear if no error
1019 ; ERROR 'C' set if error
1020 ; EXIT: (ax) = error code
1021 ; ('error_lock_violation' if conflicting locks)
1023 ; CHANGE 04/15/87 - First release
1026 ;******************* END OF SPECIFICATIONS *************************************
1027 ;******************+ START OF PSEUDOCODE +**************************************
1031 ; search till count = 0
1035 ; clear_count = start_count - current_count
1036 ; loop till clear_count = 0
1043 ; set successful status
1049 ;******************+ END OF PSEUDOCODE +**************************************
1051 Procedure Clr_List
,NEAR
1053 ;; $do ;an000;while cx not = 0
1054 ;; cmp cx,00 ;an000;at end?
1055 ;; $leave e ;an000;yes
1056 ;; push cx ;an000;save cx - our counter
1057 ;; push di ;an000;save di - our SFT pointer
1058 call load_regs
;an000;set up for clr_block call
1059 ;; push bp ; save pointer to range entry ;AN000;
1060 call clr_block
;an000;remove the lock
1061 ;; pop bp ; recover pointer to range entry ;AN000;
1062 ;; pop di ;an000;restore our SFT pointer
1063 ;; pop cx ;an000;restore cx - our counter
1064 ;; $leave c ;an000;leave on error
1065 ;; dec cx ;an000;decrease counter
1068 ;; $if c ;an000;an error occurred
1069 ;; push bp ;an000;save bp
1070 ;; mov bp,sp ;an000;get sp
1071 ;; mov dx,[bp].parm_1 ;an000;recover original index
1072 ;; mov ax,[bp].Parm_2 ; original count ;AN000;
1074 ;; SUB AX,CX ; how many did we do? ;AN000;
1075 ;; MOV CX,AX ; set up the loop ;AN000;
1076 ;; MOV BP,DX ; save the index ;AN000;
1079 ;; cmp cx,00 ;an000;at end?
1080 ;; $leave e ;an000;yes
1081 ;; push cx ;an000;save cx - our counter
1082 ;; push di ;an000;save di - our SFT pointer
1083 ;; call load_regs ;an000;set up for set_block call
1084 ;; call set_block ;an000;reset the locks
1085 ;; pop di ;an000;restore our SFT pointer
1086 ;; pop cx ;an000;restore cx - our counter
1087 ;; $leave c ;an000;leave on error
1088 ;; dec cx ;an000;decrease counter
1090 ;; stc ;an000;signal an error
1092 ;; clc ;an000;signal no error
1095 ;; ret 4 ; return (clear Parm_1 & Parm_2) ;AN000;
1096 ret ; return (clear Parm_1 & Parm_2) ;AC006;
1101 BREAK <Set_Block
- Try to set a
lock>
1103 ;******************* START OF SPECIFICATIONS ***********************************
1105 ; NAME: Set_Block - set byte range lock on a file
1107 ; FUNCTION: Set_Block sets a lock on a specified range of a file. An
1108 ; error is returned if the lock conflicts with another.
1109 ; Locks are cleared via clr_block.
1111 ; INPUT: (ES:DI) = SFT address
1112 ; (CX:DX) = offset of area
1113 ; (SI:AX) = length of area
1114 ; (BX) = 0 lock all operations
1115 ; = 1 lock write operations
1116 ; User_ID = 16-bit user id of issuer
1117 ; Proc_ID = 16-bit process id of issuer
1120 ; OUTPUT: Lock records removed for all blocks specified
1122 ; REGISTERS USED: ALL but DS, BP
1125 ; LINKAGE: Invoked by: Set_Mult_Block
1127 ; EXTERNAL Invoke: CLP (SLE), OFL
1130 ; NORMAL 'C' clear if no error
1133 ; ERROR 'C' set if error
1136 ; CHANGE 04/15/87 - lock only write support
1139 ;******************* END OF SPECIFICATIONS *************************************
1140 ;******************+ START OF PSEUDOCODE +**************************************
1144 ; if a valid SFT and
1146 ; if no lock conflicts and
1148 ; if empty lock record available
1151 ; add RLR to the chain
1154 ; set successful return status
1156 ; set error return status
1162 ;******************+ END OF PSEUDOCODE +**************************************
1164 Procedure Set_Block
,NEAR
1166 ASSUME
ES:NOTHING
,DS:NOTHING
1170 push bp ; preserve (bp) ;AN000;
1171 push ds ; preserve (ds)
1172 ;; push bx ; preserve (bx) ;AN000;
1173 cmp es:[di].sf_mft
,ZERO
1174 ; $if nz,and ; if file is SHARED and ;AC000;
1177 call clp
; do common setup code
1182 ; $if nc,and ; if no (lock conflict) error and ;AC000;
1185 ; Its ok to set this lock. Get a free block and fill it in
1187 ; (ds:si) = pointer to name record
1188 ; (ax:bx) = fba lock area
1189 ; (cx:dx) = lba lock area
1190 ; (ds:di) = pointer to pointer to previous lock
1191 ; (TOS) = saved (bx)
1192 ; (TOS+1) = saved (ds)
1193 ; (TOS+2) = saved (bp)
1195 call OFL
; (ds:di) = pointer to new, orphan lock record
1196 ; $if nc ; if space available ;AC000;
1198 mov WORD PTR [di].rlr_sptr
,bp ; store SFT offset
1199 mov WORD PTR [di].rlr_sptr
+2,es ; store SFT offset
1200 mov [di].rlr_fba
+2,ax
1201 mov [di].rlr_fba
,bx ; store lock range
1202 mov [di].rlr_lba
+2,cx
1205 ; add to front of chain
1207 ; (ds:si) = fwa MFT name record
1209 mov ax,[si].mft_lptr
1210 mov [di].rlr_next
,ax
1211 mov [si].mft_lptr
,di
1213 ; Set process ID of lock
1219 ;; pop bx ; recover lock type ;AN000;
1220 ;; push bx ; restore the stack ;AN000;
1221 ;; mov [di].rlr_type,bx ; set the rlr_type field ;AN000;
1222 clc ; we finished OK
1228 mov ax,error_lock_violation
1238 ret ; return - all set
1242 BREAK <Clr_Block
- Try to clear a
lock>
1244 ;******************* START OF SPECIFICATIONS ***********************************
1246 ; NAME: Clr_Block - clear byte range lock on a file
1248 ; FUNCTION: Clr_Block clears a lock on a specified range of a file.
1249 ; Locks are set via set_block.
1251 ; INPUT: (ES:DI) = SFT address
1252 ; (CX:DX) = offset of area
1253 ; (SI:AX) = length of area
1254 ; (BX) = 0 lock all operations
1255 ; = 1 lock write operations
1256 ; User_ID = 16-bit user id of issuer
1257 ; Proc_ID = 16-bit process id of issuer
1260 ; OUTPUT: Lock record removed for block specified.
1262 ; REGISTERS USED: ALL but DS
1265 ; LINKAGE: Invoked by: Clr_Mult_Block
1267 ; EXTERNAL Invoke: CLP (SLE), OFL
1270 ; NORMAL 'C' clear if no error
1273 ; ERROR 'C' set if error
1274 ; EXIT: (ax) = error code
1275 ; ('error_lock_violation' if conflicting locks or
1276 ; range does not exactly match previous lock)
1278 ; CHANGE 04/15/87 - lock only write support
1281 ;******************* END OF SPECIFICATIONS *************************************
1282 ;******************+ START OF PSEUDOCODE +**************************************
1286 ; if file is SHARED and
1287 ; if lock is valid and
1288 ; if SFT matches and
1289 ; if PROC_ID matches
1290 ; if lock_reqest = lock_type
1292 ; put defunct lock on free chain
1293 ; clear error status
1308 ;******************+ END OF PSEUDOCODE +**************************************
1310 Procedure Clr_Block
,NEAR
1312 ASSUME
ES:NOTHING
,DS:NOTHING
1316 ;; push bx ; save type of operation ;AN000;
1317 cmp es:[di].sf_mft
,ZERO
1319 ; $if nz,and ; if file is SHARED and ;AC000;
1323 call clp
; do common setup code
1327 pop bp ; ES:BP points to sft.
1328 ;; pop bx ; recover the type of operation ;AN000;
1330 ; $if c,and ; if lock exists and ;AC000;
1332 ; $if z,and ; if range given correctly and ;AC000;
1335 ; We've got the lock
1337 ; (ds:di) = address of pointer (offset) to previous lock record
1338 ; (es:BP) = sft address
1340 ; Now comes the tricky part. Is the lock for us? Does the lock match the SFT
1341 ; that was given us? If not, then error.
1343 mov si,[di] ; (DS:SI) = address of lock record
1344 cmp word ptr [si].rlr_sptr
,bp
1346 ; $if z,and ; if SFT matches and ;AC000;
1350 cmp word ptr [si].rlr_sptr
+2,bp
1351 ; $if z,and ; (check both words of SFT pointer) ;AC000;
1356 ;; $if z,and ; if PROC_ID matches ;AC000;
1357 ; $if z ; if PROC_ID matches ;AC006;
1360 ; Make sure that the type of request and the lock type match
1362 ;; cmp bx,lock_all ; ;AN000;
1364 ;; $IF E,OR ; if unlocking all or ;AN000;
1366 ;; mov bp,[si].rlr_type ; get lock type ;AN000;
1367 ;; cmp bp,rlr_lall ; is it lock all? ;AN000;
1369 ;; $IF NE ; if not a LOCK ALL lock ;AN000;
1371 ; The locks match the proper open invocation. Unchain the lock
1373 mov ax,[si].rlr_next
1374 mov [di],ax ; chain it out
1376 ; put defunct lock record on the free chain
1378 ; (ds:si) = address of freed lock rec
1381 mov [si].rlr_next
,ax
1385 ; $else ; we have an error ;AC000;
1391 ; $endif ; Endif - an error ;AC000;
1394 ; $if c ; If an error was found ;AC000;
1397 mov ax,error_lock_violation
1399 ; $endif ; Endif - an error was found ;AC000;
1409 BREAK <CLP
- Common Lock Preamble
>
1411 ;******************* START OF SPECIFICATIONS ***********************************
1413 ; NAME: CLP - Common Lock Preamble
1415 ; FUNCTION: This routine contains a common code fragment for set_block
1418 ; INPUT: (ES:DI) = SFT address
1419 ; (CX:DX) = offset of area
1420 ; (SI:AX) = length of area
1421 ; User_ID = 16-bit user id of issuer
1422 ; Proc_ID = 16-bit process id of issuer
1423 ; (SS) = (DS) = DOSGroup
1425 ; OUTPUT: (ds:si) = MFT address
1427 ; REGISTERS USED: ALL but ES
1430 ; LINKAGE: Invoked by: Set_Block, Clr_Block
1432 ; EXTERNAL Invoke: SLE
1435 ; NORMAL 'C' clear if no overlap
1436 ; EXIT: (ax:bx) = offset of first byte in range
1437 ; (cx:dx) = offset of last byte in range
1439 ; ERROR 'C' set if overlap
1440 ; EXIT: 'Z' set if 1-to-1 match
1441 ; (di) points to previous lock
1443 ; CHANGE 04/15/87 - lock only write support
1446 ;******************* END OF SPECIFICATIONS *************************************
1447 ;******************+ START OF PSEUDOCODE +**************************************
1454 ; set successful return status
1456 ; set error return status
1462 ;******************+ END OF PSEUDOCODE +**************************************
1466 mov bx,dx ; shuffle arguments
1468 xchg ax,cx ; (ax:bx) = offset
1469 mov cx,si ; (cx:dx) = length
1471 or si,dx ; see if length is 0
1473 ; $if nz,and ; if length is > 0 and ;AC000;
1477 adc cx,ax ; (cx:dx) = lba+1
1479 ; $if nc,or ; no carry is ok ;AC000;
1485 ; $if z ; if !> 0 then ;AC000;
1489 sub dx,1 ; (cx:dx) = lba of locked region
1496 mov si,es:[di].sf_mft
1498 mov di,1 ; Find own locks
1500 ; di points to previous lock record
1504 ; $else ; we have an error ;AC000;
1509 inc si ; carry unchanged, zero reset
1510 mov ax,error_lock_violation
; assume error
1513 ; $endif ; endif - we have an error ;AC000;
1520 BREAK <Chk_Block
- See
if the specified I
/O violates locks
>
1522 ;******************* START OF SPECIFICATIONS ***********************************
1524 ; NAME: Chk_Block - check range lock on a file
1526 ; FUNCTION: Chk_Block is called to interogate the lock status of a
1529 ; NOTE: This routine is called for every disk I/O operation
1532 ; INPUT: (ES:DI) points to an SFT structure
1533 ; (AL) = 80h - Write operation = 0 - any non write operation
1534 ; (CX) is the number of bytes being read or written
1535 ; BytPos is a long (low first) offset into the file
1537 ; User_ID = 16-bit user id of issuer
1538 ; Proc_ID = 16-bit process id of issuer
1541 ; OUTPUT: CF set according to status and presence of locks (see below)
1543 ; REGISTERS USED: ALL but ES,DI,CX,DS
1546 ; LINKAGE: IBMDOS Jump Table
1548 ; NORMAL 'C' clear if no error
1551 ; ERROR 'C' set if error
1552 ; EXIT: (ax) = error code
1553 ; ('error_lock_violation' if conflicting locks)
1555 ; CHANGE 04/15/87 - lock only write support
1558 ;******************* END OF SPECIFICATIONS *************************************
1559 ;******************+ START OF PSEUDOCODE +**************************************
1566 ; if lock conflicts occur (error)
1567 ; if this is !write operation and
1568 ; if a write lock found
1569 ; set successfull status
1582 ;******************+ END OF PSEUDOCODE +**************************************
1584 Procedure Chk_Block
,NEAR
1586 ASSUME
DS:NOTHING
,ES:NOTHING
,SS:DOSGROUP
1588 write_op equ
080h ; write operation requested ;AN000;
1589 lock_all equ 0h
; lock all specified ;AN000;
1598 ; mov ax,word ptr ds:[bx] ;ICE
1599 ; mov word ptr ds:[bx],ax ;ICE
1614 cmp es:[di].sf_mft
,0
1616 ; $if nz,and ; if the file is SHARED and ;AC000;
1621 mov si,es:[di].sf_MFT
; (DS:SI) = address of MFT record
1622 test [si].mft_lptr
,-1
1624 ; $if nz,and ; if there are locks on this file and ;AC000;
1627 sub cx,1 ; (cx) = count-1
1630 ; $if c ; there are bytes to lock ;AC000;
1633 ;; push ax ; preserve type of operation ;AN000;
1634 ; DOS passes AL = 80 for writes
1637 mov ax,WORD PTR BytPos
+2
1638 mov bx,WORD PTR BytPos
; (ax:bx) = offset
1642 adc cx,ax ; (cx:dx) = lba of lock area
1643 sub di,di ; ignore own locks
1645 ;; pop ax ; recover type of opperation ;AN000;
1647 ; upon return DS:SI points to the RLR with the conflict
1649 ;; $if c ; if lock conflicts occur - error ;AC000;
1651 ; now we must check what type of lock exists
1652 ; and the type of operation in progress.
1654 ;; cmp al,write_op ; ;AN000;
1656 ;; $if ne,and ; if NOT a write operation and ;AN000;
1658 ;; cmp [si].rlr_type,rlr_lwr ; ;AN000;
1660 ;; $if e ; if write locked (NOT all locked) ;AN000;
1662 ;; clc ; then not true conflict - clear error ;AN000;
1664 ;; $else ; else it IS a valid conflict ;AC000;
1666 ;; stc ; true error - set error status
1668 ;; $endif ; endif - a valid conflict ;AC000;
1671 ;; $endif ; endif - conflicts ;AC000;
1673 mov ax,error_lock_violation
; assume error
1675 ; $endif ; endif - no need to check ;AC000;
1680 ; 'C' and (ax) setup
1692 BREAK <MFT_get
- get an
entry from the MFT
>
1694 ;******************* START OF SPECIFICATIONS ***********************************
1696 ; MFT_get - get an entry from the MFT
1698 ; MFT_get is used to return information from the MFT. System utilities
1699 ; use this capability to produce status displays.
1701 ; MFT_get first locates the (BX)'th file in the list (no particular
1702 ; ordering is promised). It returns that name and the UID of
1703 ; the (CX)'th SFT on that file and the number of locks on that
1704 ; file via that SFT.
1706 ; ENTRY DS:SI point to DPL which contains:
1707 ; (dBX) = zero-based file index
1708 ; (dCX) = zero-based SFT index
1710 ; EXIT 'C' clear if no error
1711 ; ES:DI buffer is filled in with BX'th file name
1712 ; (BX) = user id of SFT
1713 ; (CX) = # of locks via SFT
1716 ; ('error_no_more_files' if either index is out
1719 ;******************* END OF SPECIFICATIONS *************************************
1721 Procedure MFT_get
,NEAR
1727 ASSUME
DS:NOTHING
,ES:NOTHING
1733 MOV DI,OFFSET DOSGROUP
:OpenBuf
1735 xchg bx,cx ; (cx) = file index
1739 Off
SI,mft
; (ds:si) = fwa of OFFSET MFT
1741 ; scan forward until next name
1743 mget1: cmp [si].mft_flag
,MFLG_FRE
1744 jz mget3
; is free space
1747 ; have another name. see if this satisfies caller
1749 jcxz mget4
; caller is happy
1751 mget3: add si,[si].mft_len
; skip name record
1754 ; we've located the file name.
1757 ; (DS:SI) = MFT entry
1758 ; (ES:DI) = address of caller's buffer
1761 push si ; save table offset
1764 stosb ; copy name into caller's buffer
1767 pop si ; (DS:SI) = name record address
1768 xchg bx,cx ; (cx) = SFT chain count
1769 lds di,[si].mft_sptr
1770 mget6: jcxz mget8
; have reached the SFT we wanted
1772 lds di,[di].sf_chain
; get next link
1774 jnz mget6
; follow chain some more
1775 pop di ; (es:di) = buffer address
1777 ;** The file or SFT index was too large - return w/ error
1779 mget7: mov ax,error_no_more_files
1785 ;** We've got the SFT he wants. Lets count the locks
1787 ; (es:TOS) = buffer address
1788 ; (DS:DI) = address of SFT
1789 ; (si) = address of mft
1791 mget8: mov ax,[DI].sf_flags
1792 mov dx,ds ; save segment
1795 mov si,[si].mft_lptr
; (DS:SI) = Lock record address
1796 sub cx,cx ; clear counter
1800 cmp di,WORD PTR [si].rlr_sptr
1802 cmp dx,word PTR [si].rlr_sptr
+2
1805 mget10: mov si,[si].rlr_next
1808 ; Done counting locks. return the info
1810 ; (cx) = count of locks
1811 ; (es:TOS) = buffer address
1814 mov bx,[di].SF_UID
; (bx) = UID
1823 BREAK <ASC
- Add SFT to Chain
>
1825 ;******************* START OF SPECIFICATIONS ***********************************
1827 ; ASC - Add SFT to Chain
1829 ; ASC is called to add an SFT to the front of the chain.
1831 ; ASC checks the file share mode bits on the other SFTs in the chain and
1832 ; reports a conflict. The new SFT is NOT ADDED in the case of
1835 ; ENTRY (BX) = FBA MFT name record
1836 ; (DS:SI) = SFT address
1837 ; EXIT 'C' clear if added
1838 ; (ds:si) point to sft
1839 ; (bx) offset of mft
1840 ; 'C' set if conflict
1844 ;******************* END OF SPECIFICATIONS *************************************
1849 jnz asc9
; already on chain - internal error
1851 ; The SFT looks good... lets see if there are any use conflicts
1853 ; Message 1,<"Adding sft ">
1855 mov ax,User_ID
; place user information in SFT
1856 mov [si].sf_UID
,ax ; do it before CUC (he checks UID)
1864 call CUC
; check use conflicts
1869 jc asc8
; use conflicts - forget it
1874 ; Message 1,<" to ">
1880 mov [si].sf_MFT
,bx ; make SFT point to MFT
1882 ; MessageNum [si].sf_mft
1885 mov cx,[si].sf_mode
; (cx) = open mode
1886 mov dx,ds ; (dx:si) = SFT address
1888 pop ds ; (ds:bx) = MFT address
1891 ; Not special file and no previous sft found OR normal SFT. We link it in
1892 ; at the head of the list.
1894 ; (dx:si) point to sft
1895 ; (ds:bx) point to mft
1897 les di,[bx].mft_sptr
; get first link
1898 mov word ptr [bx].mft_sptr
,si ; link in this sft
1899 mov word ptr [bx].mft_sptr
+2,dx ; link in this sft
1901 mov word ptr [si].sf_chain
,di
1902 mov word ptr [si].sf_chain
+2,es
1903 asc75: mov ds,dx ; point back to sft
1908 ; the SFT is already in use... internal error
1912 call INTERR
; NEVER RETURNS
1913 ascerr db "ASC: sft already in use", 13, 10, 0
1918 BREAK <BCS
- Bulk Close of SFTs
>
1920 ;******************* START OF SPECIFICATIONS ***********************************
1922 ; BCS - Bulk Close of SFTs
1924 ; BCS scans the MFT structures looking for SFTs that match a UID (and
1925 ; perhaps a PID). The SFTs are closed. The MFT name record is removed
1926 ; if all its SFTs are closed.
1928 ; BCS is called with a PID and a PID MASK. The SFT is closed if its UID
1929 ; matches the supplied UID AND (PID_ & PIDMASK) == PID_supplied
1931 ; We walk the MFT structure closing all relevant SFT's. There is no
1932 ; need for special handling of 70 handles or FCBs.
1934 ; Note that we call DOS_close to close the SFT; DOS_close in turn calls
1935 ; mftclose which may remove the SFT and even the MFT. This means that
1936 ; the MFT may vanish as we are working on it. Whenever we call
1937 ; DOS_close we'll know the next SFT and, if there is no next SFT we'll
1938 ; know the next MFT. (If the MFT were released a pointer to the carcass
1939 ; is not of any help. An MFT carcass cannot help find the next MFT
1942 ; ENTRY (AX) = UID to match
1948 ;******************* END OF SPECIFICATIONS *************************************
1957 Off
SI,mft
; start at beginning of buffer
1959 ; scan forward to the nearest name record (we may be at it now)
1961 ; (DS:SI) = record pointer
1963 bcs1: cmp [si].mft_flag
,MFLG_FRE
1964 jl bcs16
; at end of names, all done
1965 jg bcs2
; have a name record
1967 bcs1$5
: add si,[si].mft_len
; skip record and loop
1972 bcs2: les di,[si].mft_sptr
; got name record - get first SFT
1973 ; run down SFT chain
1975 ; (es:di) = FBA next SFT
1976 ; (ds:si) = FBA name record
1977 ; (ax) = UID to match
1982 jz bcs1$5
; at end of SFT chain
1983 cmp ax,es:[di].sf_UID
1984 jnz bcs4
; not a match
1985 mov cx,es:[di].sf_PID
1986 and cx,bx ; apply mask
1988 jz bcs51
; got a match
1990 les di,es:[di].sf_chain
1991 JMP bcs3
; chain to next SFT
1994 ; We have an SFT to close
1996 ; (es:di) = FBA SFT to be closed
1998 ; (ds:si) = FBA name record
1999 ; (ax) = UID to match
2003 bcs51: mov es:[di].sf_ref_count
,1
2006 push dx ; save ID values (ax,bx,dx) and mask
2008 push si ; save name record address (ds:si)
2009 mov si,word ptr es:[di].sf_chain
2011 jnz bcs7
; isnt last sft, MFT will remain
2013 ; yup, this is the last sft for this MFT, the MFT may evaporate. we have
2014 ; to find the next one NOW, and remember it
2016 pop si ; undo saved name record address
2018 bcs6: add si,[si].mft_len
; go to next guy
2019 cmp [si].mft_flag
,MFLG_FRE
2020 jz bcs6
; must be a non-free guy
2022 push si ; resave our new next MFT
2023 sub si,si ; no next sft
2025 ; Allright, we're ready to call the DOS.
2027 ; (es:di) = FBA sft to be closed
2028 ; ((sp)) = long address of current or next MFT
2029 ; ((sp)+4) = PID value
2030 ; ((sp)+6) = PID mask
2031 ; ((sp)+8) = UID value
2033 bcs7: mov WORD PTR ThisSFT
,di
2034 mov WORD PTR ThisSFT
+2,es
2035 mov es,word ptr es:[di].sf_chain
+2
2037 call CPS
; clear JFN
2040 CallInstall DOS_Close
,multDos
,1
2044 RestoreReg
<di,es> ; (es:DI) = offset of next sft
2046 pop ds ; (DS:SI) = fwa of current or next MFT
2051 jnz bcs85
; have more sft's
2052 JMP bcs1
; look at this new MFT
2063 BREAK <CSL
- Clear SFT Locks
>
2065 ;******************* START OF SPECIFICATIONS ***********************************
2067 ; CSL - Clear SFT Locks
2069 ; CSL clears any locks associated with this SFT.
2071 ; ENTRY (ES:DI) = SFT address
2072 ; EXIT (ES:DI) unchanged
2073 ; USES All but ES,DI
2075 ;******************* END OF SPECIFICATIONS *************************************
2079 mov si,es:[di].sf_MFT
2082 lea bx,[si].mft_lptr
; (DS:BX) = addr of lock ptr
2083 mov si,[bx] ; (DS:SI) = fba first lock record
2085 ; scan the locks looking for belongers.
2087 ; (es:di) = SFT address
2088 ; (ds:si) = this lock address
2089 ; (ds:bx) = address of link (offset value) to this lock (prev lock)
2092 jz csl3
; done with lock list
2093 cmp di,word ptr [si].rlr_sptr
2094 jnz csl2
; not my lock
2096 cmp ax,word ptr [si].rlr_sptr
+2
2097 jnz csl2
; not my lock
2099 ; Make sure that the lock REALLY belongs to the correct process
2101 cmp user_in_ax
, (ServerCall
shl 8) + 4 ; only check if ; @@01
2102 jnz csl15
; process specific; @@01
2104 cmp ax,[si].rlr_pid
; is process ID of lock = this PID?
2105 jnz csl2
; nope, skip this lock
2107 ; got a lock to remove
2110 mov dx,[si].rlr_next
2111 mov [bx],dx ; link him out
2113 mov [si].rlr_next
,ax
2115 mov si,dx ; (DS:SI) = next lock address
2118 ERRNZ rlr_next
; lock is not ours... follow chain
2120 mov si,[si].rlr_next
2131 BREAK <CUC
- check usage conflicts
>
2133 ;******************* START OF SPECIFICATIONS ***********************************
2135 ; Use conflict table
2139 ; if ((newmode == COMPAT) or (oldmode == COMPAT))
2140 ; and (user ID's match)
2143 ; for new and old mode, compute index of (SH*3)+ACC
2144 ; shift right table[new_index] by old_index+2;
2147 ; The bit in the old_index position indicates the success or failure. 0
2148 ; => allow access, 1 => fail access
2150 ;******************* END OF SPECIFICATIONS *************************************
2154 CUCA: DW 0ffffh ; Compat Read
2155 DW 0ffffh ; Compat Write
2156 DW 0ffffh ; Compat Read/Write
2157 DW 0ffffh ; Deny R/W Read
2158 DW 0ffffh ; Deny R/W Write
2159 DW 0ffffh ; Deny R/W Read/Write
2160 DW 0df7fh ; Deny W Read
2161 DW 0dbffh ; Deny W Write
2162 DW 0dfffh ; Deny W Read/Write
2163 DW 0beffh ; Deny R Read
2164 DW 0b7ffh ; Deny R Write
2165 DW 0bfffh ; Deny R Read/Write
2166 DW 01c7fh ; Deny None Read
2167 DW 003ffh ; Deny None Write
2168 DW 01fffh ; Deny None Read/Write
2170 ; 4443 3322 2111 000
2171 ; Deny/Compat / DDDD DDDD DDDD CCCx
2172 ; DenyRead / R RR RRR
2173 ; DenyWrite 1st Access =< WW WWWW
2174 ; AccessRead \ R RR RR RR R R R
2175 ; AccessWrite \ WW W W WW WW WW
2176 ; x 1111 1111 1111 1111
2177 ; C R 00 1111 1111 1111 1111 ffff
2178 ; C W 01 1111 1111 1111 1111 ffff
2179 ; C RW 02 1111 1111 1111 1111 ffff
2181 ; DRWR 10 1111 1111 1111 1111 ffff
2182 ; DRW W 11 1111 1111 1111 1111 ffff
2183 ; DRWRW 12 1111 1111 1111 1111 ffff
2184 ; D WR 20 1101 1111 0111 1111 df7f
2186 ; D W W 21 1101 1011 1111 1111 dbff
2187 ; D WRW 22 1101 1111 1111 1111 dfff
2188 ; DR R 30 1011 1110 1111 1111 beff
2189 ; DR W 31 1011 0111 1111 1111 b7ff
2191 ; DR RW 32 1011 1111 1111 1111 bfff
2192 ; D R 40 0001 1100 0111 1111 1c7f
2193 ; D W 41 0000 0011 1111 1111 03ff
2194 ; D RW 42 0001 1111 1111 1111 1fff
2196 ; In order to allow the greatest number of accesses, compatability read mode
2197 ; is treated as deny-write read. The other compatability modes are treated
2200 ;******************* START OF SPECIFICATIONS ***********************************
2202 ; CUC - check usage conflicts
2204 ; CUC is called to see if a would-be open would generate a share
2205 ; conflict with an existing open. See CUCA for the algorithm and table
2208 ; ENTRY (BX) = FBA MFT name record
2209 ; (DS:SI) = SFT address
2210 ; EXIT 'C' clear if OK
2211 ; 'C' set if conflict
2213 ; USES ALL but arguments (BX, DS:SI)
2215 ;******************* END OF SPECIFICATIONS *************************************
2221 mov di,si ; (es:di) = FBA SFT record
2222 call gom
; get open mode
2224 and ch,sharing_mask
; (ch) = new guy share
2225 jz cuc0
; new guy is compatability mode
2227 cuc0: call csi
; compute share index
2228 add ax,ax ; *2 for word index
2229 xchg ax,si ; (si) = share table index
2231 pop ds ; (ds:bx) = FBA MFT record
2232 mov dx,WORD PTR CUCA
[si] ; (dx) = share mask
2233 lds si,[bx].mft_sptr
; (ds:si) = first sft guy
2235 ; ready to do access compares.
2237 ; (ds:si) = address of next sft
2238 ; (es:di) = address of new sft
2239 ; (dx) = share word from CUCA
2240 ; (cs:bx) = MFT offset
2241 ; (ch) = 0 if new SFT is compatibilty mode, else sharing_mask
2244 jz cuc9
; at end of chain, no problems
2245 call gom
; if not FCB, then mode in al is good
2247 and ah,sharing_mask
; (ah) = sharing mode
2248 or ah,ch ; (ah) = 0 iff new and old is SH_COMP
2249 jnz cuc2
; neither is SH_COMP
2251 ; Both the old and the new guy are SH_COMP mode. If the UIDs match,
2252 ; step onward. If they don't match do normal share check.
2254 mov bp,es:[di].sf_UID
2256 jz cuc20
; equal => next sft to check
2258 cuc2: call csi
; compute the share index
2261 xchg al,cl ; (cl) = shift count
2263 sar ax,cl ; select the bit
2264 jc cuc8
; a conflict!
2266 lds si,[si].sf_chain
2267 JMP cuc1
; chain to next SFT and try again
2269 ; Have a share conflict
2271 cuc8: mov ax,error_sharing_violation
; assume share conflict
2274 ; done with compare. Restore regs and return
2276 ; 'C' set as appropriate
2277 ; (es:di) = new SFT address
2278 ; (ax) set as appropriate
2289 BREAK <csi
- compute share index
>
2291 ;******************* START OF SPECIFICATIONS ***********************************
2293 ; csi - compute share index
2296 ; If the mode byte has a leading 7 then it is interpreted as a 0
2297 ; csi turns a mode byte into an index from 0 to 14:
2299 ; (share index)*3 + (access index)
2301 ; ENTRY (al) = mode byte
2305 ;******************* END OF SPECIFICATIONS *************************************
2310 and ah,access_mask
; (ah) = access bits
2311 and al,sharing_mask
; (al) = share bites
2312 ERRNZ sharing_mask
-0F0h
2313 cmp al,sharing_net_FCB
2320 mov cl,al ; (cl) = SHVAL*2
2322 add al,cl ; (al) = SHVAL*3
2323 add al,ah ; (al) = SH*3 + ACC
2330 Break <GOM
- get open mode
>
2332 ;******************* START OF SPECIFICATIONS ***********************************
2334 ; GOM - get open mode
2336 ; Find the correct open mode given the encoded sf_mode. Note that files
2337 ; marked READ-ONLY and are opened in compatability read-only are treated as
2338 ; deny-write read-only. FCB opens are sharing_compat open_for_both and
2339 ; net FCB opens are sharing_compat
2341 ; Entry: (DS:SI) points to SFT
2342 ; Exit: (AL) has correct mode
2344 ;******************* END OF SPECIFICATIONS *************************************
2350 jz gom1
; if not FCB, then mode in al is good
2351 mov al,sharing_compat
+open_for_both
2355 cmp ah,sharing_net_FCB
; is sharing from net FCB?
2356 jnz gom2
; no, got good mode
2357 and al,access_mask
; yes, convert to compat mode sharing
2358 or al,sharing_compat
2360 ; The sharing mode and access mode in AL is now correct for the file. See if
2361 ; mode is compatability. If so and file is read-only, convert access mode to
2367 retnz
; not compatability, return.
2368 test [si].sf_attr
,attr_read_only
2369 retz
; not read-only
2370 mov al,sharing_deny_write
+ open_for_read
2382 END ; This can't be inside the if
2383 ; mode is compatability. If so and file is read-only, convert access mode to
2389 retnz
; not compatability, return.
2390 test [si].sf_attr
,attr_read_only
2391 retz
; not read-only
2392 mov al,sharing_deny_write
+ open_for_read
2404 END ; This can't be inside the if