From 2d04cacc5322951f187bb17e017c12920ac8ebe2 Mon Sep 17 00:00:00 2001 From: Mark Zbikowski Date: Thu, 25 Apr 2024 21:24:10 +0100 Subject: MZ is back! --- v4.0/src/DOS/DIR2.ASM | 1353 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1353 insertions(+) create mode 100644 v4.0/src/DOS/DIR2.ASM (limited to 'v4.0/src/DOS/DIR2.ASM') diff --git a/v4.0/src/DOS/DIR2.ASM b/v4.0/src/DOS/DIR2.ASM new file mode 100644 index 0000000..1346f43 --- /dev/null +++ b/v4.0/src/DOS/DIR2.ASM @@ -0,0 +1,1353 @@ +; SCCSID = @(#)dir2.asm 1.2 85/07/23 +; SCCSID = @(#)dir2.asm 1.2 85/07/23 +TITLE DIR2 - Directory and path cracking +NAME Dir2 +; Main Path cracking routines, low level search routines and device +; name detection routines +; +; GETPATH +; GetPathNoSet +; CHKDEV +; ROOTPATH +; FINDPATH +; StartSrch +; MatchAttributes +; DEVNAME +; Build_device_ent +; Validate_CDS +; CheckThisDevice +; +; Revision history: +; +; A000 version 4.00 Jan. 1988 +; A001 PTM 3564 -- search using fastopen + +; +; get the appropriate segment definitions +; +.xlist +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +include dossym.inc +include devsym.inc +include fastopen.inc ;DOS 3.3 +.cref +.list + +asmvar Kanji + + i_need NoSetDir,BYTE + i_need EntFree,WORD + i_need DirStart,WORD + i_need LastEnt,WORD + i_need WFP_START,WORD + i_need CURR_DIR_END,WORD + i_need CurBuf,DWORD + i_need THISCDS,DWORD + i_need Attrib,BYTE + i_need SAttrib,BYTE + i_need VolID,BYTE + i_need Name1,BYTE + i_need ThisDPB,DWORD + i_need EntLast,WORD + i_need Creating,BYTE + i_need NULDEV,DWORD + i_need DEVPT,DWORD + i_need DEVFCB,BYTE + i_need ALLOWED,BYTE + i_need EXTERR_LOCUS,BYTE + I_need FastOpenFlg,BYTE ;DOS 3.3 + I_need FastOpenTable,BYTE ;DOS 3.3 + I_need Dir_Info_Buff,BYTE ;DOS 3.3 + I_need FastOpen_Ext_Info,BYTE ;DOS 3.3 + I_need CLUSNUM,WORD ;DOS 3.3 + I_need Next_Element_Start,WORD ;DOS 3.3 + I_need HIGH_SECTOR,WORD ;AN000;>32mb + I_need DOS34_FLAG,WORD ;AN000;>32mb + + +Break + +; Inputs: +; [WFP_START] Points to WFP string ("d:\" must be first 3 chars, NUL +; terminated; d:/ (note forward slash) indicates a real device). +; [CURR_DIR_END] Points to end of Current dir part of string +; ( = -1 if current dir not involved, else +; Points to first char after last "/" of current dir part) +; [THISCDS] Points to CDS being used +; [SATTRIB] Is attribute of search, determines what files can be found +; [NoSetDir] set +; [THISDPB] set to DPB if disk otherwise garbage. +; Function: +; Crack the path +; Outputs: +; Sets EXTERR_LOCUS = errLOC_Disk if disk file +; Sets EXTERR_LOCUS = errLOC_Unk if char device +; ID1 field of [THISCDS] updated appropriately +; [ATTRIB] = [SATTRIB] +; ES:BP Points to DPB +; Carry set if bad path +; SI Points to path element causing failure +; Zero set +; [DIRSTART],[DIRSEC],[CLUSNUM], and [CLUSFAC] are set up to +; start a search on the last directory +; CL is zero if there is a bad name in the path +; CL is non-zero if the name was simply not found +; [ENTFREE] may have free spot in directory +; [NAME1] is the name. +; CL = 81H if '*'s or '?' in NAME1, 80H otherwise +; Zero reset +; File in middle of path or bad name in path or attribute mismatch +; or path too long or malformed path +; ELSE +; [CurBuf] = -1 if root directory +; [CURBUF] contains directory record with match +; [CURBUF+2]:BX Points into [CURBUF] to start of entry +; [CURBUF+2]:SI Points into [CURBUF] to dir_first field for entry +; AH = device ID +; bit 7 of AH set if device SI and BX +; will point DOSGROUP relative The firclus +; field of the device entry contains the device pointer +; [NAME1] Has name looked for +; If last element is a directory zero is set and: +; [DIRSTART],[SECCLUSPOS],[DIRSEC],[CLUSNUM], and [CLUSFAC] +; are set up to start a search on it. +; unless [NoSetDir] is non zero in which case the return is +; like that for a file (except for zero flag) +; If last element is a file zero is reset +; [DIRSEC],[CLUSNUM],[CLUSFAC],[NXTCLUSNUM],[SECCLUSPOS], +; [LASTENT], [ENTLAST] are set to continue search of last +; directory for furthur matches on NAME1 via the NEXTENT +; entry point in FindEntry (or GETENT entry in GETENTRY in +; which case [NXTCLUSNUM] and [SECCLUSPOS] need not be valid) +; DS preserved, Others destroyed + + procedure GETPATH,near + DOSAssume CS,,"GetPath" + ASSUME ES:NOTHING + + MOV WORD PTR [CREATING],0E500H ; Not Creating, not DEL *.* + +;Same as GetPath only CREATING and DELALL already set + entry GetPathNoSet + MOV [EXTERR_LOCUS],errLOC_Disk + MOV WORD PTR CurBuf,-1 ; initial setting +; +; See if the input indicates a device that has already been detected. If so, +; go build the guy quickly. Otherwise, let findpath find the device. +; + MOV DI,Wfp_Start ; point to the beginning of the name + CMP WORD PTR [DI+1],'\' SHL 8 + ':' + JZ CrackIt +; +; Let ChkDev find it in the device list +; + ADD DI,3 + MOV SI,DI ; let CHKDEV see the original name + CALL CHKDEV + JC InternalError +Build_devJ: + MOV AL,SAttrib + MOV Attrib,AL + MOV [EXTERR_LOCUS],errLOC_Unk ; In the particular case of + ; "finding" a char device + ; set LOCUS to Unknown. This makes + ; certain idiotic problems reported + ; by a certain 3 letter OEM go away. +; +; Take name in name1 and pack it back into where wfp_start points. This +; guarantees wfp_start pointing to a canonical representation of a device. +; We are allowed to do this as GetPath is *ALWAYS* called before entering a +; wfp into the share set. +; +; We copy chars from name1 to wfp_start remembering the position of the last +; non-space seen +1. This position is kept in DX. +; + Context ES + mov si,offset DOSGroup:Name1 + mov di,wfp_start + mov dx,di + mov cx,8 ; 8 chars in device name +MoveLoop: + lodsb + stosb + cmp al," " + jz nosave + IF DBCS ;AN000;; +; cmp al,81h ;AN000;; 2/23/KK +; jne notKanji ;AN000;; 2/23/KK +; cmp cx,1 ;AN000; 2/23/KK +; je notKanji ;AN000; 2/23/KK +; cmp byte ptr [si],40h ;AN000; 2/23/KK +; jne notKanji ;AN000;; 2/23/KK +; lodsb ;AN000;; 2/23/KK +; stosb ;AN000;; 2/23/KK +; dec cx ;AN000;; 2/23/KK +; jmp nosave ;AN000;; 2/23/KK +;notKanji: ;AN000;; 2/23/KK + ENDIF + mov dx,di +NoSave: + loop MoveLoop +; +; DX is the position of the last seen non-space + 1. We terminate the name +; at this point. +; + mov di,dx + mov byte ptr [di],0 ; end of string + invoke Build_device_ent ; Clears carry sets zero + INC AL ; reset zero + return + + assume es:nothing + +InternalError: + JMP InternalError ; freeze + +; +; Start off at the correct spot. Optimize if the current dir part is valid. +; +CrackIt: + MOV SI,[CURR_DIR_END] ; get current directory pointer + CMP SI,-1 ; valid? + JNZ LOOK_SING ; Yes, use it. + LEA SI,[DI+3] ; skip D:\ +LOOK_SING: + Assert ISDPB,<,>,"Crackit" + MOV Attrib,attr_directory+attr_system+attr_hidden + ; Attributes to search through Dirs + LES DI,[THISCDS] + MOV AX,-1 + MOV BX,ES:[DI.curdir_ID] + MOV SI,[CURR_DIR_END] +; +; AX = -1 +; BX = cluster number of current directory. THis number is -1 if the media +; has been uncertainly changed. +; SI = offset in DOSGroup into path to end of current directory text. This +; may be -1 if no current directory part has been used. +; + CMP SI,AX ; if Current directory is not part + JZ NO_CURR_D ; then we must crack from root + CMP BX,AX ; is the current directory cluster valid + +; DOS 3.3 6/25/86 + JZ NO_CURR_D ; no, crack form the root + TEST [FastOpenFlg],FastOpen_Set ; for fastopen ? + JZ GOT_SEARCH_CLUSTER ; no + PUSH ES ; save registers + PUSH DI + PUSH CX + PUSH [SI-1] ; save \ and 1st char of next element + PUSH SI + PUSH BX + + MOV BYTE PTR [SI-1],0 ; call fastopen to look up cur dir info + MOV SI,[Wfp_Start] + MOV BX,OFFSET DOSGROUP:FastOpenTable + MOV DI,OFFSET DOSGROUP:Dir_Info_Buff + MOV CX,OFFSET DOSGROUP:FastOpen_Ext_Info + MOV AL,FONC_look_up + PUSH DS + POP ES + CALL DWORD PTR [BX.FASTOPEN_NAME_CACHING] + JC GO_Chk_end1 ;fastopen not installed, or wrong drive. Go to Got_Srch_cluster + CMP BYTE PTR [SI],0 ;fastopen has current dir info? + JE GO_Chk_end ;yes. Go to got_serch_cluster + stc + jmp short GO_Chk_end ;Go to No_Curr_D +GO_Chk_end1: + clc +GO_Chk_end: ; restore registers + POP BX + POP SI + POP [SI-1] + POP CX + POP DI + POP ES + JNC GOT_SEARCH_CLUSTER ; crack based on cur dir + +; DOS 3.3 6/25/86 +; +; We must cract the path beginning at the root. Advance pointer to beginning +; of path and go crack from root. +; +NO_CURR_D: + MOV SI,[WFP_START] + LEA SI,[SI+3] ; Skip "d:/" + LES BP,[THISDPB] ; Get ES:BP + JMP ROOTPATH +; +; We are able to crack from the current directory part. Go set up for search +; of specified cluster. +; +GOT_SEARCH_CLUSTER: + LES BP,[THISDPB] ; Get ES:BP + invoke SETDIRSRCH + JC SETFERR + JMP FINDPATH + +SETFERR: + XOR CL,CL ; set zero + STC + Return + +EndProc GETPATH + +; Check to see if the name at DS:DI is a device. Returns carry set if not a +; device. +; Blasts CX,SI,DI,AX,BX + +Procedure ChkDev,NEAR + ASSUME ES:Nothing,DS:NOTHING + + MOV SI,DI + MOV DI,SS + MOV ES,DI + ASSUME ES:DOSGroup ; Now here is where ES is DOSGroup + + MOV DI,OFFSET DOSGROUP:NAME1 + MOV CX,9 +TESTLOOP: + invoke GETLET + IF DBCS ;AN000; + invoke Testkanj ;AN000;; 2/13/KK + jz Notkanja ;AN000;; 2/13/KK + stosb ;AN000;; Skip second byte 2/13/KK + dec cx ;AN000;; 2/13/KK + jcxz notdev ;AN000;; 2/13/KK + lodsb ;AN000;; 2/13/KK + jmp short stowit ;AN000;; 2/13/KK +Notkanja: ;AN000; + ENDIF ;AN000; + CMP AL,'.' + JZ TESTDEVICE + invoke PATHCHRCMP + JZ NOTDEV + OR AL,AL + JZ TESTDEVICE +stowit: + STOSB + LOOP TESTLOOP +NOTDEV: + STC + return + +TESTDEVICE: + ADD CX,2 + MOV AL,' ' + REP STOSB + MOV AX,SS + MOV DS,AX + invoke DEVNAME + return +EndProc ChkDev + +Break + +; Inputs: +; Same as FINDPATH but, +; SI Points to asciz string of path which is assumed to start at +; the root (no leading '/'). +; Function: +; Search from root for path +; Outputs: +; Same as FINDPATH but: +; If root directory specified, [CURBUF] and [NAME1] are NOT set, and +; [NoSetDir] is ignored. + + procedure ROOTPATH,near + + DOSAssume CS,,"RootPath" + ASSUME ES:NOTHING + + invoke SETROOTSRCH + CMP BYTE PTR [SI],0 + JNZ FINDPATH + +; Root dir specified + MOV AL,SAttrib + MOV Attrib,AL + XOR AH,AH ; Sets "device ID" byte, sets zero + ; (dir), clears carry. + return + +; Inputs: +; [ATTRIB] Set to get through directories +; [SATTRIB] Set to find last element +; ES:BP Points to DPB +; SI Points to asciz string of path (no leading '/'). +; [SECCLUSPOS] = 0 +; [DIRSEC] = Phys sec # of first sector of directory +; [CLUSNUM] = Cluster # of next cluster +; [CLUSFAC] = Sectors per cluster +; [NoSetDir] set +; [CURR_DIR_END] Points to end of Current dir part of string +; ( = -1 if current dir not involved, else +; Points to first char after last "/" of current dir part) +; [THISCDS] Points to CDS being used +; [CREATING] and [DELALL] set +; Function: +; Parse path name +; Outputs: +; ID1 field of [THISCDS] updated appropriately +; [ATTRIB] = [SATTRIB] +; ES:BP Points to DPB +; [THISDPB] = ES:BP +; Carry set if bad path +; SI Points to path element causing failure +; Zero set +; [DIRSTART],[DIRSEC],[CLUSNUM], and [CLUSFAC] are set up to +; start a search on the last directory +; CL is zero if there is a bad name in the path +; CL is non-zero if the name was simply not found +; [ENTFREE] may have free spot in directory +; [NAME1] is the name. +; CL = 81H if '*'s or '?' in NAME1, 80H otherwise +; Zero reset +; File in middle of path or bad name in path +; or path too long or malformed path +; ELSE +; [CURBUF] contains directory record with match +; [CURBUF+2]:BX Points into [CURBUF] to start of entry +; [CURBUF+2]:SI Points to fcb_FIRCLUS field for entry +; [NAME1] Has name looked for +; AH = device ID +; bit 7 of AH set if device SI and BX +; will point DOSGROUP relative The firclus +; field of the device entry contains the device pointer +; If last element is a directory zero is set and: +; [DIRSTART],[SECCLUSPOS],[DIRSEC],[CLUSNUM], and [CLUSFAC] +; are set up to start a search on it, +; unless [NoSetDir] is non zero in which case the return is +; like that for a file (except for zero flag) +; If last element is a file zero is reset +; [DIRSEC],[CLUSNUM],[CLUSFAC],[NXTCLUSNUM],[SECCLUSPOS], +; [LASTENT], [ENTLAST] are set to continue search of last +; directory for furthur matches on NAME1 via the NEXTENT +; entry point in FindEntry (or GETENT entry in GETENTRY in +; which case [NXTCLUSNUM] and [SECCLUSPOS] need not be valid) +; Destroys all other registers + + entry FINDPATH + DOSAssume CS,,"FindPath" + ASSUME ES:NOTHING + + Assert ISDPB,,"FindPath" + PUSH ES ; Save ES:BP + PUSH SI + MOV DI,SI + MOV CX,[DIRSTART] ; Get start clus of dir being searched + CMP [CURR_DIR_END],-1 + JZ NOIDS ; No current dir part + CMP DI,[CURR_DIR_END] + JNZ NOIDS ; Not to current dir end yet + LES DI,[THISCDS] + MOV ES:[DI.curdir_ID],CX ; Set current directory currency +NOIDS: +; +; Parse the name off of DS:SI into NAME1. AL = 1 if there was a meta +; character in the string. CX,DI may be destroyed. +; +; invoke NAMETRANS +; MOV CL,AL +; +; The above is the slow method. The name has *already* been munged by +; TransPath so no special casing needs to be done. All we do is try to copy +; the name until ., \ or 0 is hit. +; + MOV AX,SS + MOV ES,AX + MOV DI,OFFSET DOSGroup:Name1 + MOV AX,' ' + STOSB + STOSW + STOSW + STOSW + STOSW + STOSW + MOV DI,OFFSET DOSGroup:Name1 + XOR AH,AH ; bits for CL + IF DBCS ;AN000; +;-------------------------- Start of DBC;AN000;S 2/13/KK + XOR CL,CL ;AN000;; clear count for volume id + LODSB ;AN000;;IBMJ fix 9/04/86 + CMP AL,05h ;AN000;;IBMJ fix 9/04/86 + JNE GetNam2 ;AN000;;IBMJ fix 9/04/86 + PUSH AX ;AN000; ;IBMJ fix 9/04/86 + MOV AL,0E5h ;AN000;;IBMJ fix 9/04/86 + Invoke TestKanj ;AN000;;IBMJ fix 9/04/86 + POP AX ;AN000; ;IBMJ fix 9/04/86 + JZ Notkanjb ;AN000; ;IBMJ fix 9/04/86 + JMP SHORT GetNam3 ;AN000;;IBMJ fix 9/04/86 +;-------------------------- End of DBCS ;AN000;2/13/KK + ENDIF +GetNam: + INC CL ;AN000; KK incrment volid count + LODSB + IF DBCS ;AN000; +GetNam2: ;AN000;; 2/13/KK + invoke Testkanj ;AN000;; 2/13/KK + jz Notkanjb ;AN000;; 2/13/KK +GetNam3: ;AN000;; 2/13/KK + STOSB ;AN000;; 2/13/KK + INC CL ;AN000;; KK incrment volid count + LODSB ;AN000;; 2/13/KK + TEST [DOS34_FLAG],DBCS_VOLID ;AN000;; 2/13/KK + JZ notvol ;AN000;; 2/13/KK + CMP CL,8 ;AN000;; 2/13/KK + JNZ notvol ;AN000;; 2/13/KK + CMP AL,'.' ;AN000;; 2/13/KK + JNZ notvol ;AN000;; 2/13/KK + LODSB ;AN000;; 2/13/KK +notvol: ;AN000; + jmp short StoNam ;AN000;; 2/13/KK +Notkanjb: ;AN000;; 2/13/KK + ENDIF ;AN000; + CMP AL,'.' + JZ setExt + OR AL,AL + JZ GetDone + CMP AL,'\' + JZ GetDone + CMP AL,'?' + JNZ StoNam + OR AH,1 +StoNam: STOSB + JMP GetNam +SetExt: + MOV DI,OFFSET DOSGroup:Name1+8 +GetExt: + LODSB + IF DBCS ;AN000; + invoke TestKanj ;AN000;; 2/13/KK + jz Notkanjc ;AN000;; 2/13/KK + STOSB ;AN000;; 2/13/KK + LODSB ;AN000;; 2/13/KK + jmp short StoExt ;AN000;; 2/13/KK +Notkanjc: ;AN000;; 2/13/KK + ENDIF ;AN000; + OR AL,AL + JZ GetDone + CMP AL,'\' + JZ GetDone + CMP AL,'?' + JNZ StoExt + OR AH,1 +StoExt: STOSB + JMP GetExt +GetDone: + DEC SI + MOV CL,AH + + + OR CL,80H + POP DI ; Start of this element + POP ES ; Restore ES:BP + CMP SI,DI + JNZ check_device + JMP BADPATH ; NUL parse (two delims most likely) +check_device: + PUSH SI ; Start of next element + MOV AL,BYTE PTR [SI] + OR AL,AL + JNZ NOT_LAST + +; +; for last element of the path switch to the correct search attributes +; + MOV BH,SAttrib + MOV Attrib,BH +NOT_LAST: + +; +; check name1 to see if we have a device... +; + PUSH ES ; Save ES:BP + context ES + invoke DevName ; blast BX + POP ES ; Restore ES:BP + ASSUME ES:NOTHING + JC FindFile ; Not a device + OR AL,AL ; Test next char again + JZ GO_BDEV + JMP FileInPath ; Device name in middle of path + +GO_BDEV: + POP SI ; Points to NUL at end of path + JMP Build_devJ + +FindFile: + ASSUME ES:NOTHING +;;;; 7/28/86 + CMP BYTE PTR [NAME1],0E5H ; if 1st char = E5 + JNZ NOE5 ; no + MOV BYTE PTR [NAME1],05H ; change it to 05 +NOE5: + +;;;; 7/28/86 + PUSH DI ; Start of this element + PUSH ES ; Save ES:BP + PUSH CX ; CL return from NameTrans +;DOS 3.3 FastOPen 6/12/86 F.C. + + CALL LookupPath ; call fastopen to get dir entry + JNC DIR_FOUND ; found dir entry + +;DOS 3.3 FastOPen 6/12/86 F.C. + invoke FINDENTRY +DIR_FOUND: + POP CX + POP ES + POP DI + JNC LOAD_BUF + JMP BADPATHPOP + +LOAD_BUF: + LDS DI,[CURBUF] +ASSUME DS:NOTHING + TEST BYTE PTR [BX+dir_attr],attr_directory + JNZ GO_NEXT ; DOS 3.3 + JMP FileInPath ; Error or end of path +; +; if we are not setting the directory, then check for end of string +; +GO_NEXT: + CMP BYTE PTR [NoSetDir],0 + JZ SetDir + MOV DX,DI ; Save pointer to entry + MOV CX,DS + context DS + POP DI ; Start of next element + TEST [FastOpenFlg],FastOpen_Set ;only DOSOPEN can take advantage of + JZ nofast ; the FastOpen + TEST [FastOpenFlg],Lookup_Success ; Lookup just happened + JZ nofast ; no + MOV DI,[Next_Element_Start] ; no need to insert it again +nofast: + CMP BYTE PTR [DI],0 + JNZ NEXT_ONE ; DOS 3.3 + JMP SetRet ; Got it +NEXT_ONE: + PUSH DI ; Put start of next element back on stack + MOV DI,DX + MOV DS,CX ; Get back pointer to entry +ASSUME DS:NOTHING + +SetDir: + MOV DX,[SI] ; Dir_first + +;DOS 3.3 FastOPen 6/12/86 F.C. + + PUSH DS ; save [curbuf+2] + context DS ; set DS Dosgroup + TEST [FastOpenFlg],Lookup_Success ; + JZ DO_NORMAL ; fastopen not in memory or path not + MOV BX,DX ; not found + MOV DI,[CLUSNUM] ; clusnum was set in LookupPath + PUSH AX ; save device id (AH) + invoke SETDIRSRCH + POP AX ; restore device id (AH) + ADD SP,2 ; pop ds in stack + JMP FAST_OPEN_SKIP + +DO_NORMAL: +ASSUME DS:NOTHING + POP DS ; DS = [curbuf + 2] +;DOS 3.3 FastOPen 6/12/86 F.C. + + SUB BX,DI ; Offset into sector of start of entry + SUB SI,DI ; Offset into sector of dir_first + PUSH BX + PUSH AX + PUSH SI + PUSH CX + PUSH WORD PTR [DI.buf_sector] ;AN000;>32mb + PUSH WORD PTR [DI.buf_sector+2] ;AN000;>32mb + MOV BX,DX + context DS + invoke SETDIRSRCH ; This uses UNPACK which might blow + ; the entry sector buffer + POP [HIGH_SECTOR] + POP DX + JC SKIP_GETB + MOV [ALLOWED],allowed_RETRY + allowed_FAIL + XOR AL,AL + invoke GETBUFFR ; Get the entry buffer back +SKIP_GETB: + POP CX + POP SI + POP AX + POP BX + JNC SET_THE_BUF + POP DI ; Start of next element + MOV SI,DI ; Point with SI + JMP SHORT BADPATH + +SET_THE_BUF: + invoke SET_BUF_AS_DIR + MOV DI,WORD PTR [CURBUF] + ADD SI,DI ; Get the offsets back + ADD BX,DI +; DOS 3.3 FasOpen 6/12/86 F.C. + +FAST_OPEN_SKIP: + + POP DI ; Start of next element + CALL InsertPath ; insert dir entry info + +; DOS 3.3 FasOpen 6/12/86 F.C. + + + MOV AL,[DI] + OR AL,AL + JZ SETRET ; At end + INC DI ; Skip over "/" + MOV SI,DI ; Point with SI + invoke PATHCHRCMP + JNZ find_bad_name ; oops + JMP FINDPATH ; Next element + +find_bad_name: + DEC SI ; Undo above INC to get failure point +BADPATH: + XOR CL,CL ; Set zero + JMP SHORT BADPRET + +FILEINPATH: + POP DI ; Start of next element + context DS ; Got to from one place with DS gone +; DOS 3.3 FastOpen + + TEST [FastOpenFlg],FastOpen_Set ; do this here is we don't want to + JZ NO_FAST ; device info to fastopen + TEST [FastOpenFlg],Lookup_Success + JZ NO_FAST + MOV DI,[Next_Element_Start] ; This takes care of one time lookup + ; success +NO_FAST: + +; DOS 3.3 FastOpen + + MOV AL,[DI] + OR AL,AL + JZ INCRET + MOV SI,DI ; Path too long + JMP SHORT BADPRET + +INCRET: +; DOS 3.3 FasOpen 6/12/86 F.C. + + CALL InsertPath ; insert dir entry info + +; DOS 3.3 FasOpen 6/12/86 F.C. + INC AL ; Reset zero +SETRET: + return + +BADPATHPOP: + POP SI ; Start of next element + MOV AL,[SI] + MOV SI,DI ; Start of bad element + OR AL,AL ; zero if bad element is last, non-zero if path too long +BADPRET: + MOV AL,SAttrib + MOV Attrib,AL ; Make sure return correct + STC + return +EndProc ROOTPATH + +Break + +; Inputs: +; [THISDPB] Set +; Function: +; Set up a search for GETENTRY and NEXTENTRY +; Outputs: +; ES:BP = Drive parameters +; Sets up LASTENT, ENTFREE=ENTLAST=-1, VOLID=0 +; Destroys ES,BP,AX + + procedure StartSrch,NEAR + DOSAssume CS,,"StartSrch" + ASSUME ES:NOTHING + + Assert ISDPB,<,>,"StartSrch" + LES BP,[THISDPB] + XOR AX,AX + MOV [LASTENT],AX + MOV BYTE PTR [VOLID],AL ; No volume ID found + DEC AX + MOV [ENTFREE],AX + MOV [ENTLAST],AX + return +EndProc StartSrch + +BREAK + +; +; Input: [Attrib] = attribute to search for +; CH = found attribute +; Output: JZ +; JNZ +; Registers modified: noneski + procedure MatchAttributes,near + ASSUME DS:NOTHING,ES:NOTHING + PUSH AX + MOV AL,Attrib ; AL <- SearchSet + NOT AL ; AL <- SearchSet' + AND AL,CH ; AL <- SearchSet' and FoundSet + AND AL,attr_all ; AL <- SearchSet' and FoundSet and Important +; +; the result is non-zero if an attribute is not in the search set +; and in the found set and in the important set. This means that we do not +; have a match. Do a JNZ or JZ +; + POP AX + return +EndProc MatchAttributes + +Break + +; Inputs: +; DS,ES:DOSGROUP +; Filename in NAME1 +; ATTRIB set so that we can error out if looking for Volume IDs +; Function: +; Determine if file is in list of I/O drivers +; Outputs: +; Carry set if not a device +; ELSE +; Zero flag set +; BH = Bit 7,6 = 1, bit 5 = 0 (cooked mode) +; bits 0-4 set from low byte of attribute word +; DEVPT = DWORD pointer to Device header of device +; BX destroyed, others preserved + + procedure DEVNAME,NEAR + DOSAssume CS,,"DevName" + + PUSH SI + PUSH DI + PUSH CX + PUSH AX + +; E5 special code + PUSH WORD PTR [NAME1] + CMP [NAME1],5 + JNZ NOKTR + MOV [NAME1],0E5H +NOKTR: + + TEST Attrib,attr_volume_id ; If looking for VOL id don't find devs + JNZ RET31 + MOV SI,OFFSET DOSGROUP:NULDEV +LOOKIO: +ASSUME DS:NOTHING + TEST [SI.SDEVATT],DEVTYP + JZ SKIPDEV ; Skip block devices (NET and LOCAL) + MOV AX,SI + ADD SI,SDEVNAME + MOV DI,OFFSET DOSGROUP:NAME1 + MOV CX,4 ; All devices are 8 letters + REPE CMPSW ; Check for name in list + MOV SI,AX + JZ IOCHK ; Found it? +SKIPDEV: + LDS SI,DWORD PTR [SI] ; Get address of next device + CMP SI,-1 ; At end of list? + JNZ LOOKIO +RET31: STC ; Not found +RETNV: MOV CX,SS + MOV DS,CX + ASSUME DS:DOSGroup + POP WORD PTR [NAME1] + POP AX + POP CX + POP DI + POP SI + RET + +IOCHK: +ASSUME DS:NOTHING + MOV WORD PTR [DEVPT+2],DS ; Save pointer to device + MOV BH,BYTE PTR [SI.SDEVATT] + OR BH,0C0H + AND BH,NOT 020H ; Clears Carry + MOV WORD PTR [DEVPT],SI + JMP RETNV +EndProc DevName + +BREAK + +; Inputs: +; [NAME1] has name +; BH is attribute field (supplied by DEVNAME) +; [DEVPT] points to device header (supplied by DEVNAME) +; Function: +; Build a directory entry for a device at DEVFCB +; Outputs: +; BX points to DEVFCB +; SI points to dir_first field +; AH = input BH +; AL = 0 +; dir_first = DEVPT +; Zero Set, Carry Clear +; DS,ES,BP preserved, others destroyed + + procedure Build_device_ent,near + DOSAssume CS,,"Build_Device_Ent" + + MOV AX," " + MOV DI,OFFSET DOSGROUP:DEVFCB+8 ; Point to extent field +; +; Fill dir_ext +; + STOSW + STOSB ; Blank out extent field + MOV AL,attr_device +; +; Fill Dir_attr +; + STOSB ; Set attribute field + XOR AX,AX + MOV CX,10 +; +; Fill dir_pad +; + REP STOSW ; Fill rest with zeros + invoke DATE16 + MOV DI,OFFSET DOSGROUP:DEVFCB+dir_time + XCHG AX,DX +; +; Fill dir_time +; + STOSW + XCHG AX,DX +; +; Fill dir_date +; + STOSW + MOV SI,DI ; SI points to dir_first field + MOV AX,WORD PTR [DEVPT] +; +; Fill dir_first +; + STOSW ; Dir_first points to device + MOV AX,WORD PTR [DEVPT+2] +; +; Fill dir_size_l +; + STOSW + MOV AH,BH ; Put device atts in AH + MOV BX,OFFSET DOSGROUP:DEVFCB + XOR AL,AL ; Set zero, clear carry + return +EndProc Build_device_ent + +Break + +; +; ValidateCDS - Get current CDS. Splice it. Call FatReadCDS to check +; media. If media has been changed, do DOS_Chdir to validate path. If +; invalid, reset original CDS to root. +; +; Inputs: ThisCDS points to CDS of interest +; SS:DI points to temp buffer +; Outputs: The current directory string is validated on the appropriate +; drive +; ThisDPB changed +; ES:DI point to CDS +; Carry set if error (currently user FAILed to I 24) +; Registers modified: all + +Procedure ValidateCDS,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup +Public DIR2001S,DIR2001E +DIR2001S: + LocalVar Temp,WORD + LocalVar SaveCDS,DWORD +DIR2001E: + Enter + MOV Temp,DI + LDS SI,ThisCDS + MOV SaveCDSL,SI + MOV SaveCDSH,DS + EnterCrit critDisk + TEST [SI].curdir_flags,curdir_isnet ; Clears carry + JZ DoSplice + JMP FatFail +DoSplice: + XOR DL,DL + XCHG DL,NoSetDir + Context ES + Invoke FStrcpy + MOV SI,Temp + Context DS + Invoke Splice + ASSUME DS:NOTHING + Context DS ; FatReadCDS (ThisCDS); + MOV NoSetDir,DL + LES DI,ThisCDS + SaveReg + Invoke FatRead_CDS + RestoreReg + JC FatFail + LDS SI,ThisCDS ; if (ThisCDS->ID == -1) { + ASSUME DS:NOTHING + CMP [SI].curdir_ID,-1 + JNZ RestoreCDS + Context ES + SaveReg ; t = wfp_Start; + CMP SI,SaveCDSL ; if not spliced + JNZ DoChdir + MOV DI,Temp + MOV wfp_Start,DI ; wfp_start = d; + Invoke FStrCpy ; strcpy (d, ThisCDS->Text); +DoChdir: + Context DS + SaveReg <,BP> ; c = DOSChDir (); + Invoke DOS_ChDir + RestoreReg ; wfp_Start = t; + MOV SAttrib,BL + LDS SI,SaveCDS + ASSUME DS:NOTHING + JNC SetCluster ; if (c == -1) { + MOV WORD PTR ThisCDS,SI ; ThisCDS = TmpCDS; + MOV WORD PTR ThisCDS+2,DS + XOR CX,CX ; TmpCDS->text[3] = c = 0; + MOV [SI+3],CL ; } +SetCluster: + MOV [SI].curdir_ID,-1 ; TmpCDS->ID = -1; + LDS SI,ThisCDS ; ThisCDS->ID = c; + TEST [SI].curdir_flags,curdir_splice ;AN000;;MS. for Join and Subst + JZ setdirclus ;AN000;;MS. + MOV CX,-1 ;AN000;;MS. +setdirclus: + MOV [SI].curdir_ID,CX ; } +RestoreCDS: + LES DI,SaveCDS + MOV WORD PTR ThisCDS,DI + MOV WORD PTR ThisCDS+2,ES + CLC +FatFail: + LeaveCrit critDisk + LES DI,SaveCDS + Leave + return +EndProc ValidateCDS + +Break + +; +; CheckThisDevice - Examine the area at DS:SI to see if there is a valid +; device specified. We will return carry if there is a device present. The +; forms of devices we will recognize are: +; +; [path]device +; +; Note that the drive letter has *already* been removed. All other forms +; are not considered to be devices. If such a device is found we change the +; source pointer to point to the device component. +; +; Inputs: ES is DOSGroup +; DS:SI contains name +; Outputs: ES is DOSGroup +; DS:SI point to name or device +; Carry flag set if device was found +; Carry flag reset otherwise +; Registers Modified: all except ES:DI, DS + +if FALSE +Procedure CheckThisDevice,NEAR + DOSAssume CS,,"CheckThisDevice" + ASSUME DS:NOTHING + SaveReg +; +; Advance to after the final path character. +; + MOV DI,SI ; remember first character +PathSkip: + LODSB + OR AL,AL + JZ FoundEnd + IF DBCS ;AN000; + invoke Testkanj ;AN000;; 2/13/KK + jz Notkanje ;AN000;; 2/13/KK + lodsb ;AN000;; 2/13/KK + or al,al ;AN000;; Skip second byte 2/13/KK removed + jz FoundEnd ;AN000;; 2/13/KK removed + jmp Short Pathskip ;AN000;; Ignore missing second byte for now. +NotKanje: ;AN000; + ENDIF ;AN000; +;kanji load of next char too 2/13/KK +IF Kanji + kanji load of next char too +ENDIF + invoke PathChrCmp ; is it a path char? + JNZ PathSkip + MOV DI,SI + JMP PathSkip +FoundEnd: + MOV SI,DI +; +; Parse the name +; + SaveReg ; preserve the source pointer + invoke NameTrans ; advance DS:SI + CMP BYTE PTR [SI],0 ; parse entire string? + STC ; simulate a Carry return from DevName + JNZ SkipSearch ; no parse. simulate a file return. + Context DS + Invoke DevName + ASSUME DS:NOTHING +SkipSearch: + RestoreReg +; +; DS:SI points to the beginning of the potential device. If we have a device +; then we do not change SI. If we have a file, then we reset SI back to the +; original value. At this point Carry set indicates FILE. +; + RestoreReg ; get original SI + JNC CheckDone ; if device then do not reset pointer + MOV SI,DI +CheckDone: + RestoreReg + CMC ; invert carry. Carry => device + return +else +Procedure CheckThisDevice,NEAR + DOSAssume CS,,"CheckThisDevice" + ASSUME DS:NOTHING + SaveReg + MOV DI,SI +; +; Check for presence of \dev\ (Dam multiplan!) +; + MOV AL,[SI] + Invoke PathChrCmp ; is it a path char? + JNZ ParseDev ; no, go attempt to parse device + INC SI ; simulate LODSB +; +; We have the leading path separator. Look for DEV part. +; + LODSW + OR AX,2020h + CMP AX,"e" SHL 8 + "d" + JNZ NotDevice ; not "de", assume not device + LODSB + OR AL,20h + CMP AL,"v" ; Not "v", assume not device + JNZ NotDevice + LODSB + invoke PathChrCmp ; do we have the last path separator? + JNZ NotDevice ; no. go for it. +; +; DS:SI now points to a potential drive. Preserve them as NameTrans advances +; SI and DevName may destroy DS. +; +ParseDev: + SaveReg ; preserve the source pointer + invoke NameTrans ; advance DS:SI + CMP BYTE PTR [SI],0 ; parse entire string? + STC ; simulate a Carry return from DevName + JNZ SkipSearch ; no parse. simulate a file return. + Context DS + Invoke DevName + ASSUME DS:NOTHING +SkipSearch: + RestoreReg +; +; SI points to the beginning of the potential device. If we have a device +; then we do not change SI. If we have a file, then we reset SI back to the +; original value. At this point Carry set indicates FILE. +; +CheckReturn: + RestoreReg ; get original SI + JNC CheckDone ; if device then do not reset pointer + MOV SI,DI +CheckDone: + RestoreReg + CMC ; invert carry. Carry => device + return +NotDevice: + STC + JMP CheckReturn +endif + +EndProc CheckThisDevice + +BREAK + +; +; Output DS:SI -> path name, +; ES:DI -> dir entry info buffer +; ES:CX -> extended dir info buffer +; +; carry flag clear : tables pointed by ES:DI and ES:CX are filled by +; FastOpen, DS:SI points to char just one after +; the last char of path name which is fully or +; partially found in FastOPen +; carry flag set : FastOpen not in memory or path name not found +; + procedure LookupPath,NEAR + ASSUME ES:NOTHING + +; PUSH AX + TEST [FastOpenFlg],FastOpen_Set ; flg is set in DOSPEN + JNZ FASTINST ; and this routine is +NOLOOK: + JMP NOLOOKUP ; executed once +FASTINST: + TEST [FastOpenFlg],No_Lookup ; no more lookup? + JNZ NOLOOK ; yes + + MOV BX,OFFSET DOSGROUP:FastOpenTable ; get fastopen related tab + MOV SI,[Wfp_Start] ; si points to path name + MOV DI,OFFSET DOSGROUP:Dir_Info_Buff + MOV CX,OFFSET DOSGROUP:FastOpen_Ext_Info + MOV AL,FONC_look_up ; al = 1 + PUSH DS + POP ES + CALL DWORD PTR [BX.FASTOPEN_NAME_CACHING] ;call fastopen + JC NOTFOUND ; fastopen not in memory + + LEA BX,[SI-2] + CMP BX,[Wfp_Start] ; path found ? + JZ NOTFOUND ; no + ; fully or partially found + CMP BYTE PTR [SI],0 ;AN000;FO. + JNZ parfnd ;AN000;FO.; partiallyfound + PUSH CX ;AN000;FO.; is attribute matched ? + MOV CL,Attrib ;AN000;FO.; + MOV CH,Sattrib ;AN000;FO.; attrib=sattrib + MOV Attrib,CH ;AN000;FO.; + MOV CH,ES:[DI.dir_attr] ;AN000;FO.; + invoke Matchattributes ;AN000;FO.; +;;; MOV Attrib,CL ;AN001;FO.; retore attrib + POP CX ;AN000;FO.; + JNZ NOLOOKUP ;AN000;FO.; not matched +parfnd: + MOV [Next_Element_Start],SI ; save si + MOV BX,CX + MOV AX,[BX.FEI_lastent] ;AN000;;FO. restore lastentry + MOV [LASTENT],AX ;AN000;;FO. + MOV AX,[BX.FEI_dirstart] ;AN001;;FO. restore dirstart + MOV [DIRSTART],AX ;AN001;;FO. + MOV AX,[BX.FEI_clusnum] ; restore next cluster num + MOV [CLUSNUM],AX ; + + PUSH ES ; save ES + LES BX,[THISDPB] ; put drive id + MOV AH,ES:[BX.dpb_drive] ; in AH for DOOPEN + POP ES ; pop ES + + MOV WORD PTR [CURBUF+2],ES ; [curbuf+2].bx points to + MOV BX,DI ; start of entry + LEA SI,[DI.dir_first] ; [curbuf+2]:si points to + ; dir_first field in the + ; dir entry + OR [FastOpenFlg],Lookup_Success + set_for_search +; POP AX + RET +NOTFOUND: + CMP AX,-1 ; not in memory ? + JNZ Partial_Success ; yes, in memory + MOV [FastOpenFlg],0 ; no more fastopen +Partial_Success: + AND [FastOpenFlg],Special_Fill_Reset +NOLOOKUP: +; POP AX + STC + RET +EndProc LookupPath + +BREAK + +; +; Input: FastOpen_Set flag set when from DOSOPEN otherwise 0 +; Lookup_Success flag set when got dir entry info from FASTOPEN +; DS = DOSGROUP +; Output: FastOPen_Ext_Info is set and path dir info is inserted +; + procedure InsertPath,NEAR + ASSUME ES:NOTHING + + PUSHF + TEST [FastOpenFlg],FastOpen_Set ;only DOSOPEN can take advantage of + JZ GET_NEXT_ELEMENT ; the FastOpen + TEST [FastOpenFlg],Lookup_Success ; Lookup just happened + JZ INSERT_DIR_INFO ; no + AND [FastOpenFlg],Lookup_Reset ; we got dir info from fastopen so + MOV DI,[Next_Element_Start] ; no need to insert it again + JMP GET_NEXT2 +INSERT_DIR_INFO: ; save registers + PUSH DS + PUSH ES + PUSH BX + PUSH SI + PUSH DI + PUSH CX + PUSH AX +; int 3 + LDS DI,[CURBUF] ; DS:DI -> buffer header +ASSUME DS:NOTHING + MOV SI,OFFSET DOSGROUP:FastOpen_Ext_Info + MOV AX,WORD PTR [DI.buf_sector] ; get directory sector + MOV WORD PTR CS:[SI.FEI_dirsec],AX ;AN000; >32mb save dir sector + MOV AX,WORD PTR [DI.buf_sector+2] ;AN000; >32mb + context DS + MOV WORD PTR [SI.FEI_dirsec+2],AX ;AN000;>32mb save high dir sector + MOV AX,[CLUSNUM] ; save next cluster number + MOV [SI.FEI_clusnum],AX + MOV AX,[LASTENT] ;AN000;FO. save lastentry for search first + MOV [SI.FEI_lastent],AX ;AN000;FO. + MOV AX,[DIRSTART] ;AN001;FO. save for search first + MOV [SI.FEI_dirstart],AX ;AN001;FO. + + MOV AX,BX + ADD DI,BUFINSIZ ; DS:DI -> start of data in buffer + SUB AX,DI ; AX=BX relative to start of sector + MOV CL,SIZE dir_entry +;invoke debug_DOS + DIV CL + MOV [SI.FEI_dirpos],AL ; save directory entry # in buffer + + PUSH DS + POP ES + + MOV DS,WORD PTR [CURBUF+2] + MOV DI,BX ; DS:DI -> dir entry info +ASSUME DS:NOTHING + CMP DS:[DI.dir_first],0 ; never insert info when file is empty + JZ SKIP_INSERT ; e.g. newly created file + + PUSH SI ; ES:BX -> extended info + POP BX + + MOV AL,FONC_insert ; call fastopen insert operation + MOV SI,OFFSET DOSGROUP:FastOpenTable + CALL DWORD PTR ES:[SI.FASTOPEN_NAME_CACHING] + + CLC +SKIP_INSERT: + POP AX + POP CX ; restore registers + POP DI + POP SI + POP BX + POP ES + POP DS +GET_NEXT2: + OR [FastOpenFlg],No_Lookup ; we got dir info from fastopen so +GET_NEXT_ELEMENT: + POPF + RET +EndProc InsertPath + +CODE ENDS + END -- cgit v1.2.3