     1                                  ;	SCCSID = @(#)macro2.asm 1.2 85/07/23
     2                                  ;TITLE	MACRO2 - Pathname and macro related internal routines
     3                                  ;NAME	MACRO2
     4                                  ;
     5                                  ;   TransFCB	    written
     6                                  ;   TransPath	    written
     7                                  ;   TransPathSet    written
     8                                  ;   TransPathNoSet  Written
     9                                  ;   Canonicalize    written
    10                                  ;   PathSep	    written
    11                                  ;   SkipBack	    written
    12                                  ;   CopyComponent   written
    13                                  ;   Splice	    written
    14                                  ;   $NameTrans	    written
    15                                  ;   DriveFromText
    16                                  ;   TextFromDrive
    17                                  ;   PathPref
    18                                  ;   ScanPathChar
    19                                  ;
    20                                  ;   Revision history:
    21                                  ;
    22                                  ;	Created: MZ 4 April 1983
    23                                  ;		 MZ 18 April 1983   Make TransFCB handle extended FCBs
    24                                  ;		 AR 2 June 1983     Define/Delete macro for NET redir.
    25                                  ;		 MZ 3 Nov 83	    Fix InitCDS to reset length to 2
    26                                  ;		 MZ 4 Nov 83	    Fix NetAssign to use STRLEN only
    27                                  ;		 MZ 18 Nov 83	    Rewrite string processing for subtree
    28                                  ;				    aliasing.
    29                                  ;		 BAS 3 Jan 85	    ScanPathChar to search for path separator
    30                                  ;				    in null terminated string.
    31                                  ;
    32                                  ;   MSDOS performs several types of name translation.  First, we maintain for
    33                                  ;   each valid drive letter the text of the current directory on that drive.
    34                                  ;   For invalid drive letters, there is no current directory so we pretend to
    35                                  ;   be at the root.  A current directory is either the raw local directory
    36                                  ;   (consisting of drive:\path) or a local network directory (consisting of
    37                                  ;   \\machine\path.  There is a limit on the point to which a ..  is allowed.
    38                                  ;
    39                                  ;   Given a path, MSDOS will transform this into a real from-the-root path
    40                                  ;   without .  or ..  entries.	Any component that is > 8.3 is truncated to
    41                                  ;   this and all * are expanded into ?'s.
    42                                  ;
    43                                  ;   The second part of name translation involves subtree aliasing.  A list of
    44                                  ;   subtree pairs is maintained by the external utility SUBST.	The results of
    45                                  ;   the previous 'canonicalization' are then examined to see if any of the
    46                                  ;   subtree pairs is a prefix of the user path.  If so, then this prefix is
    47                                  ;   replaced with the other subtree in the pair.
    48                                  ;
    49                                  ;   A third part involves mapping this "real" path into a "physical" path.  A
    50                                  ;   list of drive/subtree pairs are maintained by the external utility JOIN.
    51                                  ;   The output of the previous translation is examined to see if any of the
    52                                  ;   subtrees in this list are a prefix of the string.  If so, then the prefix
    53                                  ;   is replaced by the appropriate drive letter.  In this manner, we can
    54                                  ;   'mount' one device under another.
    55                                  ;
    56                                  ;   The final form of name translation involves the mapping of a user's
    57                                  ;   logical drive number into the internal physical drive.  This is
    58                                  ;   accomplished by converting the drive number into letter:CON, performing
    59                                  ;   the above translation and then converting the character back into a drive
    60                                  ;   number.
    61                                  ;
    62                                  ;   curdir_list     STRUC
    63                                  ;   curdir_text     DB	    DIRSTRLEN DUP (?) ; text of assignment and curdir
    64                                  ;   curdir_flags    DW	    ?		    ; various flags
    65                                  ;   curdir_devptr   DD	    ?		    ; local pointer to DPB or net device
    66                                  ;   curdir_ID	    DW	    ?		    ; cluster of current dir (net ID)
    67                                  ;		    DW	    ?
    68                                  ;   curdir_end	    DW	    ?		    ; end of assignment
    69                                  ;   curdir_list     ENDS
    70                                  ;   curdir_netID    EQU     DWORD PTR curdir_ID
    71                                  ;   ;Flag word masks
    72                                  ;   curdir_isnet    EQU     1000000000000000B
    73                                  ;   curdir_inuse    EQU     0100000000000000B
    74                                  ;
    75                                  ;
    76                                  ;   There are two main entry points:  TransPath and TransFCB.  TransPath will
    77                                  ;   take a path and form the real text of the pathname with all .  and ..
    78                                  ;   removed.  TransFCB will translate an FCB into a path and then invoke
    79                                  ;   TransPath.
    80                                  ;
    81                                  ;   Implementation note:  CURDIR_End field points to the point in the text
    82                                  ;   string where the user may back up to via ..  It is the location of a
    83                                  ;   separator character.  For the root, it points at the leading /.  For net
    84                                  ;   assignments it points at the end (nul) of the initial assignment:
    85                                  ;   A:/     \\foo\bar	    \\foo\bar\blech\bozo
    86                                  ;     ^ 	     ^		     ^
    87                                  ; A: -> d: /path/ path/ text
    88                                  ;
    89                                  ;   A000  version 4.00  Jan. 1988
    90                                  
    91                                  [list -]
    91          ******************       warning: redefining multi-line macro `struc' [-w+pp-macro-redef-multi]
    14                              <4> [list -]
    14                              <3> [list -]
     3                              <2> 
     4                              <2> addsection DOSSTART, align=16 PUBLIC class=DOSSTART
     5                              <2> ; (no prior section) ; DOSSTART		ENDS
     6                              <2> 
     7                              <2> addsection DOSSTARTJUMP, align=1 PUBLIC class=START
     8                              <2> ; (no prior section) ; DOSSTARTJUMP		ENDS
     9                              <2> 
    10                              <2> addsection CONSTANTS, align=2 PUBLIC class=CONST
    11                              <2> ; (no prior section) ; CONSTANTS	ENDS
    12                              <2> 
    13                              <2> addsection DATA, align=2 PUBLIC class=DATA
    14                              <2> ; (no prior section) ; DATA		ENDS
    15                              <2> 
    16                              <2> addsection TABLE, align=2 PUBLIC class=TABLE
    17                              <2> ; (no prior section) ; TABLE		ENDS
    18                              <2> 
    19                              <2> addsection DOSDATATABLE, align=2 PUBLIC class=DOSDATACODE
    20                              <2> ; (no prior section) ; DOSDATATABLE		ENDS
    21                              <2> 
    22                              <2> addsection DOSDATACODE, align=1 PUBLIC class=DOSDATACODE
    23                              <2> ; (no prior section) ; DOSDATACODE		ENDS
    24                              <2> 
    25                              <2> addsection DOSBIODATA, align=2 PUBLIC class=DOSBIODATA
    26                              <2> 
    27                              <2> addsection LAST, align=16 PUBLIC class=LAST
    28                              <2> ; (no prior section) ; LAST		ENDS
    29                              <2> 
    30                              <2> group DOSGROUP DOSSTART DOSSTARTJUMP CONSTANTS DATA TABLE DOSDATATABLE DOSDATACODE DOSBIODATA LAST
     8                              <1> 
     9                              <1> %include "dcodeseg.nas"
     1                              <2> 
     2                              <2> %ifndef DCODESEGNAS
     3                              <2> %assign DCODESEGNAS 1
     4                              <2> 
     5                              <2> section DOSCODETABLE align=2 PUBLIC class=DOSCODE
     6                              <2> ; (no prior section) ; DOSCODETABLE		ENDS
     7                              <2> section DOSCODECODE align=1 PUBLIC class=DOSCODE
     8                              <2> ; (no prior section) ; DOSCODECODE		ENDS
     9                              <2> section DOSBIOCODE align=2 PUBLIC class=DOSCODE
    10                              <2> section BIOCODE	align=2 PUBLIC class=DOSCODE
    11                              <2> 
    12                              <2> %ifnidni DOSENTRYGROUP, DOSCODEGROUP
    13                              <2>  group DOSCODEGROUP DOSCODETABLE DOSCODECODE DOSBIOCODE BIOCODE
    14                              <2> %endif
    15                              <2> 
    16                              <2> %endif
    10                              <1> 
    11                              <1> section LAST
    12                              <1> ; (no prior section) ; LAST		ENDS
    96                                  
    97                                  [list +]
    98                                  section DOSCODECODE
    99                                  [list -]
    99          ******************       warning: out: ... for DOS Version 4.00 ... [-w+user]
    99          ******************       warning: out: BPB.INC... [-w+user]
    99          ******************       warning: out: ... CLONE version build switch on ... [-w+user]
    99          ******************       warning: out: DEVSYM.INC... [-w+user]
   106                                  ;.sall
   107                                  
   108                                  %iassign Installed TRUE
   109                                  
   110                                  	I_need	Splices,BYTE		; TRUE => splices are being done.
   111                                  	I_need	WFP_Start,WORD		; pointer to beginning of expansion
   112                                  	I_need	Curr_Dir_End,WORD	; offset to end of current dir
   113                                  	I_need	ThisCDS,DWORD		; pointer to CDS used
   114                                  	I_need	ThisDPB,DWORD		; pointer to DPB used
   115                                  	I_need	NAME1,11		; Parse output of NameTrans
   116                                  	I_need	OpenBuf,128		; ususal destination of strings
   117                                  	I_need	ExtFCB,BYTE		; flag for extended FCBs
   118                                  	I_need	Sattrib,BYTE		; attribute of search
   119                                  	I_need	fSplice,BYTE		; TRUE => do splice after canonicalize
   120                                  	I_need	fSharing,BYTE		; TRUE => no redirection allowed
   121                                  	I_Need	NoSetDir,BYTE		; TRUE => syscall is interested in
   122                                  					; entry, not contents.	We splice only
   123                                  					; inexact matches
   124                                  	I_Need	cMeta,BYTE		; count of meta chars in path
   125                                  	I_Need	Temp_Var,WORD		;AN000; variable for temporary use 3/31/KK
   126                                  	I_Need	DOS34_FLAG,WORD 	;AN000; variable for dos34
   127                                  	I_Need	NO_FILTER_PATH,DWORD	;AN000; pointer to orignal path
   128                                  section DOSCODETABLE
   129                                  	EXTRN	CharType:BYTE
   130                                  section DOSCODECODE
   131                                  
   132                                  BREAK <TransFCB - convert an FCB into a path, doing substitution>
   133                                  
   134                                  ;
   135                                  ;   TransFCB - Copy an FCB from DS:DX into a reserved area doing all of the
   136                                  ;	gritty substitution.
   137                                  ;
   138                                  ;   Inputs:	DS:DX - pointer to FCB
   139                                  ;		ES:DI - point to destination
   140                                  ;   Outputs:	Carry Set - invalid path in final map
   141                                  ;		Carry Clear - FCB has been mapped into ES:DI
   142                                  ;		    Sattrib is set from possibly extended FCB
   143                                  ;		    ExtFCB set if extended FCB found
   144                                  ;   Registers modified: most
   145                                  
   146                                  Procedure   TransFCB,NEAR
   146          ******************       warning: proc TransFCB... [-w+user]
   147                                   ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGroup
   148                                  PUBLIC MACRO001S,MACRO001E
   149                                  MACRO001S:
   150                                  	LocalVar    FCBTmp,16
   151                                  MACRO001E:
   152 00000000 5589E583EC10            	Enter
   153 00000006 1607                    	Context ES			; get DOSGroup addressability
   154 00000008 0657                    	SaveReg <ES,DI> 		; save away final destination
   155 0000000A 8D7EF0                  	LEA	DI,[FCBTmp]		; point to FCB temp area
   156 0000000D 368326[0000]00          	and word [ss:ExtFCB], 0		; clear ExtFCB and Sattrib
   157                                  	; MOV	byte [ss:ExtFCB],0		; no extended FCB found
   158                                  	; MOV	byte [ss:Sattrib],0		; default search attributes
   159 00000013 E8(0000)                	invoke	GetExtended		; get FCB, extended or not
   160 00000016 740C                    	JZ	GetDrive		; not an extended FCB, get drive
   161 00000018 8A44FF                  	MOV	AL,[SI-1]		; get attributes
   162                                  SAttrib equ Sattrib	; NASM port label
   163 0000001B 36A2[0000]              	MOV	[ss:SAttrib],AL		; store search attributes
   164 0000001F 36FE0E[0000]            	dec	byte [ss:ExtFCB]	; = 255, signal extended FCB
   165                                  GetDrive:
   166 00000024 AC                      	LODSB				; get drive byte
   167 00000025 E8(0000)                	invoke	GetThisDrv
   168 00000028 722C                    	jc	BadPack
   169 0000002A E88103                  	CALL	TextFromDrive		; convert 0-based drive to text
   170                                  ;
   171                                  ; Scan the source to see if there are any illegal chars
   172                                  ;
   173                                  DOSGroup equ DOSGROUP	; NASM port equate
   174 0000002D BB[0000]                	MOV	BX,OFFSET CharType
   175                                   %IF  DBCS				;AN000;
   176                                  ;----------------------------- Start of DBCS 2/13/KK
   177                                  	SaveReg <SI>			;AN000;; back over name, ext
   178                                  	MOV	CX,8			;AN000;; 8 chars in main part of name
   179                                  FCBScan:LODSB				;AN000;; get a byte
   180                                  	invoke	testkanj		;AN000;
   181                                  	jz	notkanj2		;AN000;
   182                                  	DEC	CX			;AN000;
   183                                  	JCXZ	VolidChck		;AN000;; Kanji half char screw up
   184                                  	LODSB				;AN000;; second kanji byte
   185                                  Nextch equ NextCh	; NASM port label
   186                                  	jmp	short Nextch		;AN000;
   187                                  VolidChck:				;AN000;
   188                                  	TEST	byte [ss:SAttrib],attr_volume_id ;AN000;; volume id ?
   189                                  Badpack equ BadPack	; NASM port label
   190                                  	JZ	Badpack 		 ;AN000;; no, error
   191                                  	OR	word [ss:DOS34_FLAG],DBCS_VOLID  ;AN000;; no, error
   192                                  	DEC	CX			 ;AN000;; cx=-1
   193                                  	INC	SI			 ;AN000;; next char
   194                                  	JMP	SHORT FCBScango 	 ;AN000;
   195                                  notkanj2:				 ;AN000;
   196                                  	cs xlatb		 ;AN000;;get bits
   197                                  	TEST	AL,fFCB 		 ;AN000;
   198                                  	JZ	BadPack 		 ;AN000;
   199                                  NextCh: 				 ;AN000;
   200                                  	LOOP	FCBScan 		 ;AN000;
   201                                  FCBScango:				 ;AN000;
   202                                  	ADD	CX,3			;AN000;; Three chars in extension
   203                                  FCBScanE:				;AN000;
   204                                  	LODSB				;AN000;
   205                                  	invoke	testkanj		;AN000;
   206                                  	jz	notkanj3		;AN000;
   207                                  	DEC	CX			;AN000;
   208                                  	JCXZ	BadPack 		;AN000;; Kanji half char problem
   209                                  	LODSB				;AN000;; second kanji byte
   210                                  	jmp	short NextChE		;AN000;
   211                                  notkanj3:				;AN000;
   212                                  	cs xlatb		;AN000;; get bits
   213                                  	TEST	AL,fFCB 		;AN000;
   214                                  	JZ	BadPack 		;AN000;
   215                                  NextChE:				;AN000;
   216                                  	LOOP	FCBScanE		;AN000;
   217                                  ;----------------------------- End of DBCS 2/13/KK
   218                                   %ELSE
   219                                  
   220 00000030 B90B00                  	MOV	CX,11
   221 00000033 56                      	SaveReg <SI>			; back over name, ext
   222 00000034 AC                      FCBScan:LODSB				; get a byte
   223 00000035 2ED7                    	cs xlatb		; get bits
   224 00000037 A808                    	TEST	AL,fFCB
   225 00000039 741B                    	JZ	BadPack
   226 0000003B E2F7                    NextCh: LOOP	FCBScan
   227                                   %ENDIF
   228 0000003D 5E                      	RestoreReg  <SI>
   229 0000003E 89FB                    	MOV	BX,DI
   230 00000040 E8(0000)                	invoke	PackName		; crunch the path
   231 00000043 5F07                    	RestoreReg  <DI,ES>		; get original destination
   232 00000045 161F                    	Context DS			; get DS addressability
   233 00000047 8D76F0                  	LEA	SI,[FCBTmp]		; point at new pathname
   234 0000004A 803F00                  	CMP	BYTE PTR [BX],0
   235 0000004D 7407                    	JZ	BadPack
   236 0000004F 55                      	SaveReg <BP>
   237 00000050 E80D00                  	CALL	TransPathSet		; convert the path
   238 00000053 5D                      	RestoreReg  <BP>
   239 00000054 7303                    	JNC	FCBRet			; bye with transPath error code
   240                                  BadPack:
   241 00000056 F9                      	STC
   242 00000057 B003                    	MOV	AL,error_path_not_found
   243 00000059 89EC5D                  FCBRet: Leave
   244 0000005C C3                      	return
   245                                  EndProc TransFCB,NoCheck
   246                                  
   247                                  BREAK <TransPath - copy a path, do string sub and put in current dir>
   248                                  
   249                                  ;
   250                                  ;   TransPath - copy a path from DS:SI to ES:DI, performing component string
   251                                  ;	substitution, insertion of current directory and fixing .  and ..
   252                                  ;	entries.  Perform splicing.  Allow input string to match splice
   253                                  ;	exactly.
   254                                  ;
   255                                  ;   TransPathSet - Same as above except No splicing is performed if input path
   256                                  ;	matches splice.
   257                                  ;
   258                                  ;   TransPathNoSet - No splicing/local using is performed at all.
   259                                  ;
   260                                  ;   The following anomalous behaviour is required:
   261                                  ;
   262                                  ;	Drive letters on devices are ignored.  (set up DummyCDS)
   263                                  ;	Paths on devices are ignored. (truncate to 0-length)
   264                                  ;	Raw net I/O sets ThisCDS => NULL.
   265                                  ;	fSharing => dummyCDS and no subst/splice.  Only canonicalize.
   266                                  ;
   267                                  ;   Other behaviour:
   268                                  ;
   269                                  ;	ThisCDS set up.
   270                                  ;	FatRead done on local CDS.
   271                                  ;	ValidateCDS done on local CDS.
   272                                  ;
   273                                  ;   Brief flowchart:
   274                                  ;
   275                                  ;	if fSharing then
   276                                  ;	    set up DummyCDS (ThisCDS)
   277                                  ;	    canonicalize (sets cMeta)
   278                                  ;	    splice
   279                                  ;	    fatRead
   280                                  ;	    return
   281                                  ;	if \\ or d:\\ lead then
   282                                  ;	    set up null CDS (ThisCDS)
   283                                  ;	    canonicalize (sets cMeta)
   284                                  ;	    return
   285                                  ;	if device then
   286                                  ;	    set up dummyCDS (ThisCDS)
   287                                  ;	    canonicalize (sets cMeta)
   288                                  ;	    return
   289                                  ;	if file then
   290                                  ;	    getCDS (sets (ThisCDS) from name)
   291                                  ;	    validateCDS (may reset current dir)
   292                                  ;	    Copy current dir
   293                                  ;	    canonicalize (set cMeta)
   294                                  ;	    splice
   295                                  ;	    generate correct CDS (ThisCDS)
   296                                  ;	    if local then
   297                                  ;		fatread
   298                                  ;	    return
   299                                  ;
   300                                  ;   Inputs:	DS:SI - point to ASCIZ string path
   301                                  ;		DI - point to buffer in DOSGroup
   302                                  ;   Outputs:	Carry Set - invalid path specification: too many .., bad
   303                                  ;		    syntax, etc. or user FAILed to I 24.
   304                                  ;		WFP_Start - points to beginning of buffer
   305                                  ;		Curr_Dir_End - points to end of current dir in path
   306                                  ;		DS - DOSGroup
   307                                  ;   Registers modified: most
   308                                  
   309                                  Procedure   TransPath,NEAR
   309          ******************       warning: proc TransPath... [-w+user]
   310                                   ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGroup
   311 0000005D 30C0                    	XOR	AL,AL
   312 0000005F A9                      	db 0A9h				; test ax, imm16 - skip mov al, -1
   313                                  	Entry	TransPathSet
   314 00000060 B0FF                    	MOV	AL,-1
   315                                  SetSplice:
   316 00000062 36A2[0000]              	MOV	[ss:NoSetDir],AL		;   NoSetDir = !fExact;
   317 00000066 B0FF                    	MOV	AL,-1
   318                                  	Entry	TransPathNoSet
   319 00000068 368936[0000]            	MOV	WORD PTR [ss:NO_FILTER_PATH],SI   ;AN000;;IFS. save old path for IFS
   320 0000006D 368C1E[0200]            	MOV	WORD PTR [ss:NO_FILTER_PATH+2],DS ;AN000;;IFS.
   321                                  
   322 00000072 36A2[0000]              	MOV	[ss:fSplice],AL		;   fSplice = TRUE;
   323 00000076 36C606[0000]FF          	MOV	byte [ss:cMeta],-1
   324 0000007C 36893E[0000]            	MOV	[ss:WFP_Start],DI
   325 00000081 36C706[0000]FFFF        	MOV	word [ss:Curr_Dir_End],-1 	; crack from start
   326 00000088 1607                    	Context ES
   327 0000008A 8DAD8600                	LEA	BP,[DI+TEMPLEN] 	; end of buffer
   328                                  ;
   329                                  ; if this is through the server dos call, fsharing is set.  We set up a
   330                                  ; dummy cds and let the operation go.
   331                                  ;
   332 0000008E 36F606[0000]FF          	TEST	byte [ss:fSharing],-1		; if no sharing
   333                                  CheckUNC equ CheckUnc	; NASM port label
   334 00000094 7435                    	JZ	CheckUNC		; skip to UNC check
   335                                  ;
   336                                  ; ES:DI point to buffer
   337                                  ;
   338 00000096 E8FA02                  	CALL	DriveFromText		; get drive and advance DS:SI
   339 00000099 E8(0000)                	invoke	GetThisDrv		; Set ThisCDS and convert to 0-based
   340 0000009C 722A                    	jc	NoPath
   341 0000009E E80D03                  	CALL	TextFromDrive		; drop in new
   342 000000A1 8D5D01                  	LEA	BX,[DI+1]		; backup limit
   343 000000A4 E83601                  	CALL	Canonicalize		; copy and canonicalize
   344 000000A7 72B3                    	retc				; errors
   345                                  ;
   346                                  ; Perform splices for net guys.
   347                                  ;
   348 000000A9 161F                    	Context DS
   349                                  wfp_Start equ WFP_Start	; NASM port label
   350 000000AB 8B36[0000]              	MOV	SI,[wfp_Start]		; point to name
   351 000000AF F606[0000]FF            	TEST	byte [fSplice],-1
   352 000000B4 7403                    	JZ	NoServerSplice
   353 000000B6 E83502                  	CALL	Splice
   354                                  NoServerSplice:
   355 000000B9 161F                    	Context DS			; for FATREAD
   356 000000BB C43E[0000]              	LES	DI,[ThisCDS]		; for fatread
   357 000000BF E8(0000)                	EnterCrit   critDisk
   358 000000C2 E8(0000)                	Invoke	FatRead_CDS
   359 000000C5 E8(0000)                	LeaveCrit   critDisk
   360                                  NoPath:
   361 000000C8 B003                    	MOV	AL,error_path_not_found ; Set up for possible bad path error
   362 000000CA C3                      	return				; any errors are in Carry flag
   363                                  	ASSUME	DS:NOTHING
   364                                  ;
   365                                  ; Let the network decide if the name is for a spooled device.  It will map
   366                                  ; the name if so.
   367                                  ;
   368                                  CheckUnc:
   369 000000CB 36C706[0000]FFFF        	MOV	WORD [ss:ThisCDS],-1	; NULL thisCDS
   370                                  multNet equ MultNET	; NASM port equate
   371 000000D2 B82311CD2F              	CallInstall NetSpoolCheck,multNet,35
   372 000000D7 7329                    	JNC	UNCDone
   373                                  ;
   374                                  ; At this point the name is either a UNC-style name (prefixed with two leading
   375                                  ; \\s) or is a local file/device.  Remember that if a net-spooled device was
   376                                  ; input, then the name has been changed to the remote spooler by the above net
   377                                  ; call.  Also, there may be a drive in front of the \\.
   378                                  ;
   379                                  NO_CHECK:
   380 000000D9 E8B702                  	CALL	DriveFromText		; eat drive letter
   381 000000DC 50                      	PUSH	AX			; save it
   382 000000DD 8B04                    	MOV	AX,WORD PTR [SI]	; get first two bytes of path
   383 000000DF E8(0000)                	Invoke	PathChrCmp		; convert to normal form
   384 000000E2 86E0                    	XCHG	AH,AL			; swap for second byte
   385 000000E4 E8(0000)                	Invoke	PathChrCmp		; convert to normal form
   386 000000E7 751F                    	JNZ	CheckDevice		; not a path char
   387 000000E9 38C4                    	CMP	AH,AL			; are they same?
   388 000000EB 751B                    	JNZ	CheckDevice		; nope
   389                                  ;
   390                                  ; We have a UNC request.  We must copy the string up to the beginning of the
   391                                  ; local machine root path
   392                                  ;
   393                                  
   394 000000ED 58                      	POP	AX
   395 000000EE A5                      	MOVSW				; get the lead \\.
   396 000000EF AC                      UNCCpy: LODSB				; get a byte
   397                                   %IF  DBCS				;AN000;
   398                                  ;----------------------------- Start of DBCS 2/23/KK
   399                                  	invoke	testkanj		;AN000;
   400                                  	jz	notkanj1		;AN000;
   401                                  	STOSB				;AN000;
   402                                  	LODSB				;AN000;
   403                                  	OR	AL,AL			;AN000;
   404                                  	JZ	UNCTerm 		;AN000;; Ignore half kanji error for now
   405                                  	STOSB				;AN000;
   406                                  	jmp	UNCCpy			;AN000;
   407                                  notkanj1:				;AN000;
   408                                  ;----------------------------- End of DBCS 2/23/KK
   409                                   %ENDIF					;AN000;
   410 000000F0 E8(0000)                	invoke	UCase			;AN000;; convert the char
   411 000000F3 08C0                    	OR	AL,AL
   412 000000F5 740E                    	JZ	UNCTerm 		; end of string.  All done.
   413 000000F7 E8(0000)                	Invoke	PathChrCmp		; is it a path char?
   414 000000FA 89FB                    	MOV	BX,DI			; backup position
   415 000000FC AA                      	STOSB
   416 000000FD 75F0                    	JNZ	UNCCpy			; no, go copy
   417 000000FF E8DB00                  	CALL	Canonicalize		; wham (and set cMeta)
   418                                  UNCDone:
   419 00000102 161F                    	Context DS
   420                                   %IF  DBCS
   421                                  ;----------------------------- Start of DBCS 2/23/KK
   422                                  	retc				;AN000; Return if error from Canonicalize
   423                                  
   424                                  ; Although Cononicalize has done lots of good things for us it may also have
   425                                  ; done e5 to 05 conversion on the fisrt char following a path sep char which is
   426                                  ; not wanted on a UNC request as this should be left for the remote station.
   427                                  ; The simplest thing to do is check for such conversions and convert them back
   428                                  ; again.
   429                                  ; This check loop is also called from the DoFile section of TransPath if the
   430                                  ; file is a remote file. Entry point when called is TP_check05 with the
   431                                  ; inputs/outputs as follows;
   432                                  ;	Inputs : ES:DI = Buffer to check for re-conversion
   433                                  ;	Outputs: None
   434                                  ;	Used   : DI,AX
   435                                  
   436                                  
   437                                  WFP_start equ WFP_Start	; NASM port label
   438                                  	MOV	DI,[WFP_start]		;AN000;; ES:DI points to converted string
   439                                  TP_check05:				;AN000;
   440                                  	MOV	AL,BYTE PTR [ES:DI]	;AN000;; Get character from path
   441                                  	OR	AL,AL			;AN000;; End of null terminated path?
   442                                  	JZ	TP_end05		;AN000;; Finished, CF =0 from OR (ret success)
   443                                  	invoke	testkanj		;AN000;; Kanji lead character?
   444                                  	JZ	TP_notK 		;AN000;; Check for path seperator if not
   445                                  	INC	DI			;AN000;; Bypass Kanji second byte
   446                                  	JMP	TP_nxt05		;AN000;; Go to check next character
   447                                  TP_notK:				;AN000;
   448                                  	invoke	PathChrCmp		;AN000;; Is it a path seperator char?
   449                                  	JNZ	TP_nxt05		;AN000;; Check next character if not
   450                                  	CMP	BYTE PTR [ES:DI+1],05	;AN000;; 05 following path sep char?
   451                                  	JNZ	TP_nxt05		;AN000;; Check next character if not
   452                                  	MOV	BYTE PTR [ES:DI+1],0E5h ;AN000;; Convert 05 back to E5
   453                                  TP_nxt05:				;AN000;
   454                                  	INC	DI			;AN000;; Point to next char in path
   455                                  	JMP	TP_check05		;AN000;; Test all chars in path
   456                                  TP_end05:
   457                                  ;----------------------------- End of DBCS 2/23/KK
   458                                   %ENDIF					;AN000;
   459 00000104 C3                      	return				; return error code
   460                                  
   461                                  	ASSUME	DS:NOTHING
   462                                  UNCTerm:
   463 00000105 AA                      	STOSB				;AN000;
   464 00000106 EBFA                    	JMP	UNCDone 		;AN000;
   465                                  
   466                                  CheckDevice:
   467                                  ;
   468                                  ; Check DS:SI for device.  First eat any path stuff
   469                                  ;
   470 00000108 58                      	POP	AX			; retrieve drive info
   471 00000109 803C00                  	CMP	BYTE PTR [SI],0	; check for null file
   472 0000010C 7504                    	JNZ	CheckPath
   473 0000010E B002                    	MOV	AL,error_file_not_found ; bad file error
   474 00000110 F9                      	STC				; signal error on null input
   475 00000111 C3                      	RETURN				; bye!
   476                                  CheckPath:
   477 00000112 5055                    	SaveReg <AX,BP> 		; save drive number
   478 00000114 E8(0000)                	Invoke	CheckThisDevice 	; snoop for device
   479 00000117 5D58                    	RestoreReg  <BP,AX>		; get drive letter back
   480 00000119 731C                    	JNC	DoFile			; yes we have a file.
   481                                  ;
   482                                  ; We have a device.  AX has drive letter.  At this point we may fake a CDS ala
   483                                  ; sharing DOS call.  We know by getting here that we are NOT in a sharing DOS
   484                                  ; call.
   485                                  ;
   486 0000011B 36C606[0000]FF          	MOV	byte [ss:fSharing],-1		; simulate sharing dos call
   487 00000121 E8(0000)                	invoke	GetThisDrv		; set ThisCDS and init DUMMYCDS
   488 00000124 36C606[0000]00          	MOV	byte [ss:fSharing],0		;
   489                                  ;
   490                                  ; Now that we have noted that we have a device, we put it into a form that
   491                                  ; getpath can understand.  Normally getpath requires d:\ to begin the input
   492                                  ; string.  We relax this to state that if the d:\ is present then the path
   493                                  ; may be a file.  If D:/ (note the forward slash) is present then we have
   494                                  ; a device.
   495                                  ;
   496 0000012A E88102                  	CALL	TextFromDrive
   497 0000012D B02F                    	MOV	AL,'/'                  ; path sep.
   498 0000012F AA                      	STOSB
   499 00000130 E8(0000)                	invoke	StrCpy			; move remainder of string
   500 00000133 F8                      	CLC				; everything OK.
   501 00000134 161F                    	Context DS			; remainder of OK stuff
   502 00000136 C3                      	return
   503                                  ;
   504                                  ; We have a file.  Get the raw CDS.
   505                                  ;
   506                                  DoFile:
   507                                  	ASSUME	DS:NOTHING
   508 00000137 E8(0000)                	invoke	GetVisDrv		; get proper CDS
   509 0000013A B003                    	MOV	AL,error_path_not_found ; Set up for possible bad file error
   510 0000013C 72F8                    	retc				; CARRY set -> bogus drive/spliced
   511                                  ;
   512                                  ; ThisCDS has correct CDS.  DS:SI advanced to point to beginning of path/file.
   513                                  ; Make sure that CDS has valid directory; ValidateCDS requires a temp buffer
   514                                  ; Use the one that we are going to use (ES:DI).
   515                                  ;
   516 0000013E 1E560657                	SaveReg <DS,SI,ES,DI>		; save all string pointers.
   517 00000142 E8(0000)                	invoke	ValidateCDS		; poke CDS amd make everything OK
   518 00000145 5F075E1F                	RestoreReg <DI,ES,SI,DS>	; get back pointers
   519 00000149 B003                    	MOV	AL,error_path_not_found ; Set up for possible bad path error
   520 0000014B 72E9                    	retc				; someone failed an operation
   521                                  ;
   522                                  ; ThisCDS points to correct CDS.  It contains the correct text of the
   523                                  ; current directory.  Copy it in.
   524                                  ;
   525 0000014D 1E56                    	SaveReg <DS,SI>
   526 0000014F 36C536[0000]            	LDS	SI,[ss:ThisCDS]		; point to CDS
   527 00000154 89FB                    	MOV	BX,DI			; point to destination
   528 00000156 035C4F                  	ADD	BX,[SI + curdir_end]	; point to backup limit
   529                                  ;	LEA	SI,[SI].curdir_text	; point to text
   530 00000159 8DAD8600                	LEA	BP,[DI+TEMPLEN] 	; regenerate end of buffer
   531                                   %IF  DBCS				;AN000;
   532                                  ;------------------------ Start of DBCS 2/13/KK
   533                                  Kcpylp: 				;AN000;
   534                                  	LODSB				;AN000;
   535                                  	invoke	TestKanj		;AN000;
   536                                  	jz	Notkanjf		;AN000;
   537                                  	STOSB				;AN000;
   538                                  	MOVSB				;AN000;
   539                                  	CMP	BYTE PTR [SI],0 	;AN000;
   540                                  	JNZ	Kcpylp			;AN000;
   541                                  	MOV	AL, '\'                 ;AN000;
   542                                  	STOSB				;AN000;
   543                                  	JMP	SHORT GetOrig		;AN000;
   544                                  Notkanjf:				;AN000;
   545                                  	STOSB				;AN000;
   546                                  	OR	AL,AL			;AN000;
   547                                  	JNZ	Kcpylp			;AN000;
   548                                  	DEC	DI			;AN000;; point to NUL byte
   549                                  
   550                                  ;------------------------ End of DBCS 2/13/KK
   551                                   %ELSE					;AN000;
   552 0000015D E8(0000)                	invoke	FStrCpy 		; copy string.	ES:DI point to end
   553 00000160 4F                      	DEC	DI			; point to NUL byte
   554                                   %ENDIF					;AN000;
   555                                  ;
   556                                  ; Make sure that there is a path char at end.
   557                                  ;
   558 00000161 B05C                    	MOV	AL,'\'
   559 00000163 263845FF                	CMP	[ES:DI-1],AL
   560 00000167 7401                    	JZ	GetOrig
   561 00000169 AA                      	STOSB
   562                                  ;
   563                                  ; Now get original string.
   564                                  ;
   565                                  GetOrig:
   566 0000016A 4F                      	DEC	DI			; point to path char
   567 0000016B 5E1F                    	RestoreReg  <SI,DS>
   568                                  ;
   569                                  ; BX points to the end of the root part of the CDS (at where a path char
   570                                  ; should be) .	Now, we decide whether we use this root or extend it with the
   571                                  ; current directory.  See if the input string begins with a leading \.
   572                                  ;
   573 0000016D E8D300                  	CALL	PathSep 		; is DS:SI a path sep?
   574 00000170 7511                    	JNZ	PathAssure		; no, DI is correct. Assure a path char
   575 00000172 08C0                    	OR	AL,AL			; end of string?
   576 00000174 7410                    	JZ	DoCanon 		; yes, skip.
   577                                  ;
   578                                  ; The string does begin with a \.  Reset the beginning of the canonicalization
   579                                  ; to this root.  Make sure that there is a path char there and advance the
   580                                  ; source string over all leading \'s.
   581                                  ;
   582 00000176 89DF                    	MOV	DI,BX			; back up to root point.
   583                                  SkipPath:
   584 00000178 AC                      	LODSB
   585 00000179 E8(0000)                	invoke PathChrCmp
   586 0000017C 74FA                    	JZ	SkipPath
   587 0000017E 4E                      	DEC	SI
   588 0000017F 08C0                    	OR	AL,AL
   589 00000181 7403                    	JZ	DoCanon
   590                                  ;
   591                                  ; DS:SI start at some file name.  ES:DI points at some path char.  Drop one in
   592                                  ; for yucks.
   593                                  ;
   594                                  PathAssure:
   595 00000183 B05C                    	MOV	AL,'\'
   596 00000185 AA                      	STOSB
   597                                  ;
   598                                  ; ES:DI point to the correct spot for canonicalization to begin.
   599                                  ; BP is the max extent to advance DI
   600                                  ; BX is the backup limit for ..
   601                                  ;
   602                                  DoCanon:
   603 00000186 E85400                  	CALL	Canonicalize		; wham.
   604 00000189 72AB                    	retc				; badly formatted path.
   605                                   %IF  DBCS				;AN000;
   606                                  ;--------------------- Start of DBCS 2/13/KK
   607                                  ; Although Cononicalize has done lots of good things for us it may also have
   608                                  ; done e5 to 05 conversion on the fisrt char following a path sep char which is
   609                                  ; not wanted if this a remote file as this should be left for the remote
   610                                  ; station. Check for a leading \\ in the path buffer and call TP_check05 to
   611                                  ; reconvert if found.
   612                                  
   613                                  	MOV	DI,[ss:WFP_start]		;AN000;; ES:DI points to string
   614                                  	MOV	AX,WORD PTR [ES:DI]	;AN000;; Get leading 2 chars from path buffer
   615                                  	invoke	PathChrCmp		;AN000;; First char a path char?
   616                                  	JNZ	TP_notremote		;AN000;; Not remote if not.
   617                                  	invoke	PathChrCmp		;AN000;; Second char a path char?
   618                                  	JNZ	TP_notremote		;AN000;; Not remote if not
   619                                  	CALL	TP_check05		;AN000;; Remote so convert 05 back to e5
   620                                  TP_notremote:				;AN000;
   621                                  ;--------------------- End of DBCS 2/13/KK
   622                                   %ENDIF
   623                                  ;
   624                                  ; The string has been moved to ES:DI.  Reset world to DOS context, pointers
   625                                  ; to wfp_start and do string substitution.  BP is still the max position in
   626                                  ; buffer.
   627                                  ;
   628 0000018B 161F                    	Context DS
   629                                  wfp_start equ WFP_Start	; NASM port label
   630 0000018D 8B3E[0000]              	MOV	DI,[wfp_start]		; DS:SI point to string
   631 00000191 C536[0000]              	LDS	SI,[ThisCDS]		; point to CDS
   632                                  	ASSUME	DS:NOTHING
   633                                  ;	LEA	SI,[SI].curdir_text	; point to text
   634 00000195 E81E02                  	CALL	PathPref		; is there a prefix?
   635 00000198 7514                    	JNZ	DoSplice		; no, do splice
   636                                  ;
   637                                  ; We have a match. Check to see if we ended in a path char.
   638                                  ;
   639                                   %IF  DBCS				;AN000;
   640                                  ;---------------------------- Start of DBCS 2/13/KK
   641                                  	PUSH	BX			;AN000;
   642                                  	MOV	BX,SI			;AN000;
   643                                  	MOV	SI,WORD PTR [ss:ThisCDS]	;AN000;; point to CDS
   644                                  LOOKDUAL:				;AN000;
   645                                  	MOV	AL,BYTE PTR [SI]	;AN000;
   646                                  	invoke	TESTKANJ		;AN000;
   647                                  	JZ	ONEINC			;AN000;
   648                                  	INC	SI			;AN000;
   649                                  	INC	SI			;AN000;
   650                                  	CMP	SI,BX			;AN000;
   651                                  	JB	LOOKDUAL		;AN000;
   652                                  	POP	BX			;AN000;; Last char was KANJI, don't look back
   653                                  	JMP	SHORT Pathline		;AN000;;  for path sep, there isn't one.
   654                                  					;AN000;
   655                                  ONEINC: 				;AN000;
   656                                  	INC	SI			;AN000;
   657                                  	CMP	SI,BX			;AN000;
   658                                  	JB	LOOKDUAL		;AN000;
   659                                  	POP	BX			;AN000;
   660                                  ;------------------------ End of DBCS 2/13/KK
   661                                   %ENDIF					;AN000;
   662 0000019A 8A44FF                  	MOV	AL,[SI-1]		; last char to match
   663 0000019D E8(0000)                	Invoke	PathChrCmp		; did we end on a path char? (root)
   664 000001A0 740C                    	JZ	DoSplice		; yes, no current dir here.
   665                                  Pathline:				; 2/13/KK
   666 000001A2 26803D00                	CMP	BYTE PTR [ES:DI],0	; end at NUL?
   667 000001A6 7406                    	JZ	DoSplice
   668 000001A8 47                      	INC	DI			; point to after current path char
   669 000001A9 36893E[0000]            	MOV	[ss:Curr_Dir_End],DI 	; point to correct spot
   670                                  ;
   671                                  ; Splice the result.
   672                                  ;
   673                                  DoSplice:
   674 000001AE 161F                    	Context DS			; back to DOSGROUP
   675 000001B0 8B36[0000]              	MOV	SI,[wfp_Start]		; point to beginning of string
   676 000001B4 31C9                    	XOR	CX,CX
   677 000001B6 F606[0000]FF            	TEST	byte [fSplice],-1
   678 000001BB 7403                    	JZ	SkipSplice
   679 000001BD E82E01                  	CALL	Splice			; replaces in place.
   680                                  SkipSplice:
   681                                  	ASSUME	DS:NOTHING
   682                                  ;
   683                                  ; The final thing is to assure ourselves that a FATREAD is done on the local
   684                                  ; device.
   685                                  ;
   686 000001C0 161F                    	Context DS
   687 000001C2 C43E[0000]              	LES	DI,[ThisCDS]		; point to correct drive
   688 000001C6 26F745430080            	TEST	word [ES:DI + curdir_flags],curdir_isnet
   689 000001CC 7401C3                  	retnz				; net, no fatread necessary
   690 000001CF E30B                    	JCXZ	Done
   691 000001D1 E8(0000)                	EnterCrit   critDisk
   692 000001D4 E8(0000)                	invoke	FatRead_CDS
   693 000001D7 E8(0000)                	LeaveCrit   critDisk
   694 000001DA B003                    	MOV	AL,error_path_not_found ; Set up for possible bad path error
   695 000001DC C3                      Done:	return				; any errors in carry flag.
   696                                  EndProc TransPath
   697                                  
   698                                  BREAK <Canonicalize - copy a path and remove . and .. entries>
   699                                  
   700                                  ;
   701                                  ;   Canonicalize - copy path removing . and .. entries.
   702                                  ;
   703                                  ;   Inputs:	DS:SI - point to ASCIZ string path
   704                                  ;		ES:DI - point to buffer
   705                                  ;		BX - backup limit (offset from ES) points to slash
   706                                  ;		BP - end of buffer
   707                                  ;   Outputs:	Carry Set - invalid path specification: too many .., bad
   708                                  ;		    syntax, etc.
   709                                  ;		Carry Clear -
   710                                  ;		    DS:DI - advanced to end of string
   711                                  ;		    ES:DI - advanced to end of canonicalized form after nul
   712                                  ;   Registers modified: AX CX DX (in addition to those above)
   713                                  
   714                                  Procedure Canonicalize,NEAR
   714          ******************       warning: proc Canonicalize... [-w+user]
   715                                   ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGroup
   716                                  ;
   717                                  ; We copy all leading path separators.
   718                                  ;
   719 000001DD AC                      	LODSB				;   while (PathChr (*s))
   720 000001DE E8(0000)                	Invoke	PathChrCmp
   721                                   %IF  DBCS
   722                                  	JNZ	CanonDec0		; 2/19/KK
   723                                   %ELSE
   724 000001E1 7507                    	JNZ	CanonDec
   725                                   %ENDIF
   726 000001E3 39EF                    	CMP	DI,BP			;	if (d > dlim)
   727 000001E5 7319                    	JAE	CanonBad		;	    goto error;
   728 000001E7 AA                      	STOSB
   729 000001E8 EBF3                    	JMP	Canonicalize		;	    *d++ = *s++;
   730                                   %IF  DBCS				;AN000;
   731                                  CanonDec0:				;AN000; 2/19/KK
   732                                  ;	mov	cs:Temp_Var,di		;AN000; 3/31/KK
   733                                   %ENDIF					;AN000;
   734                                  CanonDec:
   735 000001EA 4E                      	DEC	SI
   736                                  ;
   737                                  ; Main canonicalization loop.  We come here with DS:SI pointing to a textual
   738                                  ; component (no leading path separators) and ES:DI being the destination
   739                                  ; buffer.
   740                                  ;
   741                                  CanonLoop:
   742                                  ;
   743                                  ; If we are at the end of the source string, then we need to check to see that
   744                                  ; a potential drive specifier is correctly terminated with a path sep char.
   745                                  ; Otherwise, do nothing
   746                                  ;
   747 000001EB 31C0                    	XOR	AX,AX
   748 000001ED 3804                    	CMP	[SI],AL 		;	if (*s == 0) {
   749 000001EF 751A                    	JNZ	DoComponent
   750                                   %IF  DBCS				;AN000;
   751                                  	call	chk_last_colon		;AN000; 2/18/KK
   752                                   %ELSE					;AN000;
   753 000001F1 26807DFF3A              	CMP	BYTE PTR [ES:DI-1],':'  ;           if (d[-1] == ':')
   754                                   %ENDIF					;AN000;
   755 000001F6 7505                    	JNZ	DoTerminate
   756 000001F8 B05C                    	MOV	AL,'\'                  ;               *d++ = '\';
   757 000001FA AA                      	STOSB
   758 000001FB 88E0                    	MOV	AL,AH
   759                                  DoTerminate:
   760 000001FD AA                      	STOSB				;	    *d++ = 0;
   761 000001FE F8                      	CLC				;	    return (0);
   762 000001FF C3                      	return
   763                                   %IF  DBCS				;AN000;
   764                                  ;---------------- Start of DBCS 2/18/KK
   765                                  chk_last_colon	proc			;AN000;
   766                                  	push	si			;AN000;
   767                                  	push	ax			;AN000;
   768                                  	push	bx			;AN000;
   769                                  WFP_START equ WFP_Start	; NASM port label
   770                                  	mov	si,[ss:WFP_START]		;AN000;;PTM. for cd ..	use beginning of buf
   771                                  	cmp	si,di			;AN000;; no data stored ?
   772                                  	jb	CLC02			;AN000;;PTM. for cd ..
   773                                  	inc	si			;AN000;; make NZ flag
   774                                  	JMP	SHORT CLC09		;AN000;
   775                                  CLC02:					;AN000;
   776                                  	mov	bx,di			;AN000;
   777                                  	dec	bx			;AN000;
   778                                  CLC_lop:				;AN000;
   779                                  	cmp	si,bx			;AN000;
   780                                  	jb	CLC00			;AN000;
   781                                  	jne	CLC09			;AN000;
   782                                  CLC01:					;AN000;
   783                                  	CMP	BYTE PTR [ES:DI-1],':'  ;AN000;;           if (d[-1] == ':')
   784                                  	jmp	CLC09			;AN000;
   785                                  CLC00:					;AN000;
   786                                  	mov	al,[es:si]		;AN000;
   787                                  	inc	si			;AN000;
   788                                  	invoke	testkanj		;AN000;
   789                                  	je	CLC_lop 		;AN000;
   790                                  	inc	si			;AN000;
   791                                  	jmp	CLC_lop 		;AN000;
   792                                  CLC09:					;AN000;
   793                                  	pop	bx			;AN000;
   794                                  	pop	ax			;AN000;
   795                                  	pop	si			;AN000;
   796                                  	ret				;AN000;
   797                                  chk_last_colon	endp			;AN000;
   798                                  ;---------------- Endt of DBCS 2/18/KK
   799                                   %ENDIF					;AN000;
   800                                  
   801                                  CanonBad:
   802 00000200 E8CC01                  	CALL	ScanPathChar		; check for path chars in rest of string
   803 00000203 B003                    	MOV	AL,error_path_not_found ; Set up for bad path error
   804 00000205 7402                    	JZ	PathEnc 		; path character encountered in string
   805 00000207 B002                    	MOV	AL,error_file_not_found ; Set bad file error
   806                                  PathEnc:
   807 00000209 F9                      	STC
   808 0000020A C3                      	return
   809                                  ;
   810                                  ; We have a textual component that we must copy.  We uppercase it and truncate
   811                                  ; it to 8.3
   812                                  ;
   813                                  DoComponent:				;	    }
   814 0000020B E85200                  	CALL	CopyComponent		;	if (!CopyComponent (s, d))
   815 0000020E 72FA                    	retc				;	    return (-1);
   816                                  ;
   817                                  ; We special case the . and .. cases.  These will be backed up.
   818                                  ;
   819 00000210 26833D2E                	CMP	WORD PTR [ES:DI],'.' + (0 << 8)
   820 00000214 7408                    	JZ	Skip1
   821 00000216 26813D2E2E              	CMP	WORD PTR [ES:DI],'..'
   822 0000021B 750B                    	JNZ	CanonNormal
   823 0000021D 4F                      	DEC	DI			;	    d--;
   824 0000021E E82C00                  Skip1:	CALL	SkipBack		;	    SkipBack ();
   825 00000221 B003                    	MOV	AL,error_path_not_found ; Set up for possible bad path error
   826 00000223 72E5                    	retc
   827 00000225 EB03                    	JMP	CanonPath		;	    }
   828 00000227 90                      	nop	; identicalise
   829                                  ;
   830                                  ; We have a normal path.  Advance destination pointer over it.
   831                                  ;
   832                                  CanonNormal:				;	else
   833 00000228 01CF                    	ADD	DI,CX			;	    d += ct;
   834                                  ;
   835                                  ; We have successfully copied a component.  We are now pointing at a path
   836                                  ; sep char or are pointing at a nul or are pointing at something else.
   837                                  ; If we point at something else, then we have an error.
   838                                  ;
   839                                  CanonPath:
   840 0000022A E81600                  	CALL	PathSep
   841 0000022D 75D1                    	JNZ	CanonBad		; something else...
   842                                  ;
   843                                  ; Copy the first path char we see.
   844                                  ;
   845 0000022F AC                      	LODSB				; get the char
   846 00000230 E8(0000)                	Invoke	PathChrCmp		; is it path char?
   847 00000233 75B5                    	JNZ	CanonDec		; no, go test for nul
   848 00000235 39EF                    	CMP	DI,BP			; beyond buffer end?
   849 00000237 73C7                    	JAE	CanonBad		; yep, error.
   850 00000239 AA                      	STOSB				; copy the one byte
   851                                  ;
   852                                  ; Skip all remaining path chars
   853                                  ;
   854                                  CanonPathLoop:
   855 0000023A AC                      	LODSB				; get next byte
   856 0000023B E8(0000)                	Invoke	PathChrCmp		; path char again?
   857 0000023E 74FA                    	JZ	CanonPathLoop		; yep, grab another
   858 00000240 4E                      	DEC	SI			; back up
   859 00000241 EBA8                    	JMP	CanonLoop		; go copy component
   860                                  EndProc Canonicalize
   861                                  
   862                                  BREAK <PathSep - determine if char is a path separator>
   863                                  
   864                                  ;
   865                                  ;   PathSep - look at DS:SI and see if char is / \ or NUL
   866                                  ;   Inputs:	DS:SI - point to a char
   867                                  ;   Outputs:	AL has char from DS:SI (/ => \)
   868                                  ;		Zero set if AL is / \ or NUL
   869                                  ;		Zero reset otherwise
   870                                  ;   Registers modified: AL
   871                                  
   872                                  Procedure   PathSep,NEAR
   872          ******************       warning: proc PathSep... [-w+user]
   873                                   ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGroup
   874 00000243 8A04                    	MOV	AL,[SI] 		; get the character
   875                                  	entry	PathSepGotCh		; already have character
   876 00000245 08C0                    	OR	AL,AL			; test for zero
   877 00000247 74C1                    	retz				; return if equal to zero (NUL)
   878 00000249 E8(0000)                	invoke	PathChrCmp		; check for path character
   879 0000024C C3                      	return				; and return HIS determination
   880                                  EndProc PathSep
   881                                  
   882                                  BREAK <SkipBack - move backwards to a path separator>
   883                                  
   884                                  ;
   885                                  ;   SkipBack - look at ES:DI and backup until it points to a / \.
   886                                  ;   Inputs:	ES:DI - point to a char
   887                                  ;		BX has current directory back up limit (point to a / \)
   888                                  ;   Outputs:	ES:DI backed up to point to a path char
   889                                  ;		AL has char from output ES:DI (path sep if carry clear)
   890                                  ;		Carry set if illegal backup
   891                                  ;		Carry Clear if ok
   892                                  ;   Registers modified: DI,AL
   893                                  
   894                                  Procedure   SkipBack,NEAR
   894          ******************       warning: proc SkipBack... [-w+user]
   895                                   ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGroup
   896                                   %IF  DBCS		       ;AN000;
   897                                  ;-------------------------- Start of DBCS 2/13/KK
   898                                  	PUSH	DS		;AN000;
   899                                  	PUSH	SI		;AN000;
   900                                  	PUSH	CX		;AN000;
   901                                  	PUSH	ES		;AN000;
   902                                  	POP	DS		;AN000;
   903                                  	MOV	SI,BX		;AN000;; DS:SI -> start of ES:DI string
   904                                  	MOV	CX,DI		;AN000;; Limit of forward scan is input DI
   905                                  	MOV	AL,[SI] 	;AN000;
   906                                  	invoke	PathChrCmp	;AN000;
   907                                  	JNZ	SkipBadP	;AN000;; Backup limit MUST be path char
   908                                  	CMP	DI,BX		;AN000;
   909                                  	JBE	SkipBadP	;AN000;
   910                                  	MOV	DI,BX		;AN000;; Init backup point to backup limit
   911                                  Skiplp: 			;AN000;
   912                                  	CMP	SI,CX		;AN000;
   913                                  	JAE	SkipOK		;AN000;; Done, DI is correct backup point
   914                                  	LODSB			;AN000;
   915                                  	invoke	Testkanj	;AN000;
   916                                  Notkanjv equ NotKanjv	; NASM port label
   917                                  	jz	Notkanjv	;AN000;
   918                                  	lodsb			;AN000;; Skip over second kanji byte
   919                                  	JMP	Skiplp		;AN000;
   920                                  NotKanjv:			;AN000;
   921                                  	invoke	PathChrCmp	;AN000;
   922                                  	JNZ	Skiplp		;AN000;; New backup point
   923                                  	MOV	DI,SI		;AN000;; DI point to path sep
   924                                  	DEC	DI		;AN000;
   925                                  	jmp	Skiplp		;AN000;
   926                                  SkipOK: 			;AN000;
   927                                  	MOV	AL,[ES:DI]	;AN000;; Set output AL
   928                                  	CLC			;AN000;; return (0);
   929                                  	POP	CX		;AN000;
   930                                  	POP	SI		;AN000;
   931                                  	POP	DS		;AN000;
   932                                  	return			;AN000;
   933                                  				;AN000;
   934                                  SkipBadP:			;AN000;
   935                                  	POP	CX		;AN000;
   936                                  	POP	SI		;AN000;
   937                                  	POP	DS		;AN000;
   938                                  ;-------------------------- End of DBCS 2/13/KK
   939                                   %ELSE				;AN000;
   940 0000024D 39DF                    	CMP	DI,BX			;   while (TRUE) {
   941 0000024F 720B                    	JB	SkipBad 		;	if (d < dlim)
   942 00000251 4F                      	DEC	DI			;	    goto err;
   943 00000252 268A05                  	MOV	AL,[ES:DI]		;	if (pathchr (*--d))
   944 00000255 E8(0000)                	invoke	PathChrCmp		;	    break;
   945 00000258 75F3                    	JNZ	SkipBack		;	}
   946 0000025A F8                      	CLC				;   return (0);
   947 0000025B C3                      	return				;
   948                                   %ENDIF					;AN000;
   949                                  SkipBad:				;err:
   950 0000025C B003                    	MOV	AL,error_path_not_found ; bad path error
   951 0000025E F9                      	STC				;   return (-1);
   952 0000025F C3                      	return				;
   953                                  EndProc SkipBack
   954                                  
   955                                  Break <CopyComponent - copy out a file path component>
   956                                  
   957                                  ;
   958                                  ;   CopyComponent - copy a file component from a path string (DS:SI) into ES:DI
   959                                  ;
   960                                  ;   Inputs:	DS:SI - source path
   961                                  ;		ES:DI - destination
   962                                  ;		ES:BP - end of buffer
   963                                  ;   Outputs:	Carry Set - too long
   964                                  ;		Carry Clear - DS:SI moved past component
   965                                  ;		    CX has length of destination
   966                                  ;   Registers modified: AX,CX,DX
   967                                  
   968                                  Procedure   CopyComponent,NEAR
   968          ******************       warning: proc CopyComponent... [-w+user]
   969                                   ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGroup
   970                                  labelsize CopyBP, word, BP
   971                                  labelsize CopyD, dword, BP+2
   972                                  labelsize CopyDoff, word, BP+2
   973                                  labelsize CopyS, dword, BP+6
   974                                  labelsize CopySoff, word, BP+6
   975                                  labelsize CopyTemp, byte, BP+10
   976 00000260 83EC0E                  	SUB	SP,14			; room for temp buffer
   977 00000263 1E56065755              	SaveReg <DS,SI,ES,DI,BP>
   978 00000268 89E5                    	MOV	BP,SP
   979 0000026A B42E                    	MOV	AH,'.'
   980 0000026C AC                      	LODSB
   981 0000026D AA                      	STOSB
   982 0000026E 38E0                    	CMP	AL,AH			;   if ((*d++=*s++) == '.') {
   983 00000270 7518                    	JNZ	NormalComp
   984 00000272 E8CEFF                  	CALL	PathSep 		;	if (!pathsep(*s))
   985 00000275 740B                    	JZ	NulTerm
   986                                  TryTwoDot:
   987 00000277 AC                      	LODSB				;	    if ((*d++=*s++) != '.'
   988 00000278 AA                      	STOSB
   989 00000279 38E0                    	CMP	AL,AH
   990 0000027B 7557                    	JNZ	CopyBad
   991 0000027D E8C3FF                  	CALL	PathSep
   992 00000280 7552                    	JNZ	CopyBad 		;		|| !pathsep (*s))
   993                                  NulTerm:				;		return -1;
   994 00000282 30C0                    	XOR	AL,AL			;	*d++ = 0;
   995 00000284 AA                      	STOSB
   996 00000285 897606                  	MOV	[CopySoff],SI
   997 00000288 EB47                    	JMP	SHORT GoodRet		;	}
   998                                  NormalComp:				;   else {
   999 0000028A 8B7606                  	MOV	SI,[CopySoff]
  1000 0000028D E8(0000)                	Invoke	NameTrans		;	s = NameTrans (s, Name1);
  1001 00000290 3B7606                  	CMP	SI,[CopySOff]		;	if (s == CopySOff)
  1002 00000293 743F                    	JZ	CopyBad 		;	    return (-1);
  1003 00000295 36F606[0000]FF          	TEST	byte [ss:fSharing],-1		;	if (!fSharing) {
  1004 0000029B 7510                    	JNZ	DoPack
  1005 0000029D 80E201                  	AND	DL,1			;	    cMeta += fMeta;
  1006 000002A0 360016[0000]            	ADD	[ss:cMeta],DL		;	    if (cMeta > 0)
  1007 000002A5 7F2D                    	JG	CopyBad 		;		return (-1);
  1008 000002A7 7504                    	JNZ	DoPack			;	    else
  1009 000002A9 08D2                    	OR	DL,DL			;	    if (cMeta == 0 && fMeta == 0)
  1010 000002AB 742F                    	JZ	CopyBadPath		;		return (-1);
  1011                                  DoPack: 				;	    }
  1012 000002AD 897606                  	MOV	[CopySoff],SI
  1013 000002B0 161F                    	Context DS
  1014 000002B2 BE[0000]                	MOV	SI,OFFSET NAME1 wrt DOSGroup
  1015 000002B5 8D7E0A                  	LEA	DI,[CopyTemp]
  1016 000002B8 57                      	SaveReg <DI>
  1017 000002B9 E8(0000)                	Invoke	PackName		;	PackName (Name1, temp);
  1018 000002BC 5F                      	RestoreReg  <DI>
  1019 000002BD E8(0000)                	Invoke	StrLen			;	if (strlen(temp)+d > bp)
  1020 000002C0 49                      	DEC	CX
  1021 000002C1 034E02                  	ADD	CX,[CopyDoff]
  1022 000002C4 3B4E00                  	CMP	CX,[CopyBP]
  1023 000002C7 730B                    	JAE	CopyBad 		;	    return (-1);
  1024 000002C9 89FE                    	MOV	SI,DI			;	strcpy (d, temp);
  1025 000002CB C47E02                  	LES	DI,[CopyD]
  1026 000002CE E8(0000)                	Invoke	FStrCpy
  1027                                  GoodRet:				;	}
  1028 000002D1 F8                      	CLC
  1029 000002D2 EB0B                    	JMP	SHORT CopyEnd		;   return 0;
  1030                                  CopyBad:
  1031 000002D4 F9                      	STC
  1032 000002D5 E8F700                  	CALL	ScanPathChar		; check for path chars in rest of string
  1033 000002D8 B002                    	MOV	AL,error_file_not_found ; Set up for bad file error
  1034 000002DA 7503                    	JNZ	CopyEnd
  1035                                  CopyBadPath:
  1036 000002DC F9                      	STC
  1037 000002DD B003                    	MOV	AL,error_path_not_found ; Set bad path error
  1038                                  CopyEnd:
  1039 000002DF 5D5F075E1F              	RestoreReg  <BP,DI,ES,SI,DS>
  1040 000002E4 9F                      	LAHF
  1041 000002E5 83C40E                  	ADD	SP,14			; reclaim temp buffer
  1042 000002E8 E8(0000)                	Invoke	Strlen
  1043 000002EB 49                      	DEC	CX
  1044 000002EC 9E                      	SAHF
  1045 000002ED C3                      	return
  1046                                  EndProc CopyComponent,NoCheck
  1047                                  
  1048                                  Break <Splice - pseudo mount by string substitution>
  1049                                  
  1050                                  ;
  1051                                  ;   Splice - take a string and substitute a prefix if one exists.  Change
  1052                                  ;	ThisCDS to point to physical drive CDS.
  1053                                  ;   Inputs:	DS:SI point to string
  1054                                  ;		NoSetDir = TRUE => exact matches with splice fail
  1055                                  ;   Outputs:	DS:SI points to thisCDS
  1056                                  ;		ES:DI points to DPB
  1057                                  ;		String at DS:SI may be reduced in length by removing prefix
  1058                                  ;		and substituting drive letter.
  1059                                  ;		CX = 0 If no splice done
  1060                                  ;		CX <> 0 otherwise
  1061                                  ;		ThisCDS points to proper CDS if spliced, otherwise it is
  1062                                  ;		    left alone
  1063                                  ;		ThisDPB points to proper DPB
  1064                                  ;   Registers modified: DS:SI, ES:DI, BX,AX,CX
  1065                                  
  1066                                  Procedure   Splice,NEAR
  1066          ******************       warning: proc Splice... [-w+user]
  1067                                   ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGroup
  1068 000002EE 36F606[0000]FF          	TEST	byte [ss:Splices],-1
  1069 000002F4 746A                    	JZ	AllDone
  1070 000002F6 36FF36[0000]36FF36-     	SaveReg <<WORD PTR [ss:ThisCDS]>,<WORD PTR [ss:ThisCDS+2]>>   ; TmpCDS = ThisCDS
  1070 000002FE [0200]             
  1071 00000300 1E56                    	SaveReg <DS,SI>
  1072 00000302 5F07                    	RestoreReg <DI,ES>
  1073 00000304 31C0                    	XOR	AX,AX			;   for (i=1; s = GetCDSFromDrv (i); i++)
  1074                                  SpliceScan:
  1075 00000306 E8(0000)                	invoke	GetCDSFromDrv
  1076 00000309 724B                    	JC	SpliceDone
  1077 0000030B FEC0                    	INC	AL
  1078 0000030D F744430020              	TEST	word [SI + curdir_flags],curdir_splice
  1079 00000312 74F2                    	JZ	SpliceScan		;	if ( Spliced (i) ) {
  1080 00000314 57                      	SaveReg <DI>
  1081 00000315 E89E00                  	CALL	PathPref		;	    if (!PathPref (s, d))
  1082 00000318 7403                    	JZ	SpliceFound		;
  1083                                  SpliceSkip:
  1084 0000031A 5F                      	RestoreReg  <DI>
  1085 0000031B EBE9                    	JMP	SpliceScan		;		continue;
  1086                                  SpliceFound:
  1087 0000031D 26803D00                	CMP	BYTE PTR [ES:DI],0	;	    if (*s || NoSetDir) {
  1088 00000321 7508                    	JNZ	SpliceDo
  1089 00000323 36F606[0000]FF          	TEST	byte [ss:NoSetDir],-1
  1090 00000329 75EF                    	JNZ	SpliceSkip
  1091                                  SpliceDo:
  1092 0000032B 89FE                    	MOV	SI,DI			;		p = src + strlen (p);
  1093 0000032D 06                      	SaveReg <ES>
  1094 0000032E 1F5F                    	RestoreReg  <DS,DI>
  1095 00000330 E87D00                  	CALL	TextFromDrive1		;		src = TextFromDrive1(src,i);
  1096 00000333 36A1[0000]              	MOV	AX,[ss:Curr_Dir_End]
  1097 00000337 09C0                    	OR	AX,AX
  1098 00000339 7808                    	JS	NoPoke
  1099 0000033B 01F8                    	ADD	AX,DI			;		curdirend += src-p;
  1100 0000033D 29F0                    	SUB	AX,SI
  1101 0000033F 36A3[0000]              	MOV	[ss:Curr_Dir_End],AX
  1102                                  NoPoke:
  1103 00000343 803C00                  	CMP	BYTE PTR [SI],0 	;		if (*p)
  1104 00000346 7503                    	JNZ	SpliceCopy		;		    *src++ = '\\';
  1105 00000348 B05C                    	MOV	AL,"\"
  1106 0000034A AA                      	STOSB
  1107                                  SpliceCopy:				;		strcpy (src, p);
  1108 0000034B E8(0000)                	invoke	FStrCpy
  1109 0000034E 83C404                  	ADD	SP,4			; throw away saved stuff
  1110 00000351 80C901                  	OR	CL,1			; signal splice done.
  1111 00000354 EB0C                    	JMP	SHORT DoSet		;		return;
  1112                                  SpliceDone:				;		}
  1113                                  	ASSUME	DS:NOTHING		;   ThisCDS = TmpCDS;
  1114 00000356 368F06[0200]368F06-     	RestoreReg  <<WORD PTR [ss:ThisCDS+2]>,<WORD PTR [ss:ThisCDS]>>
  1114 0000035E [0000]             
  1115                                  AllDone:
  1116 00000360 31C9                    	XOR	CX,CX
  1117                                  DoSet:
  1118 00000362 36C536[0000]            	LDS	SI,[ss:ThisCDS]		;   ThisDPB = ThisCDS->devptr;
  1119 00000367 C47C45                  	LES	DI,[SI + curdir_devptr]
  1120 0000036A 36893E[0000]            	MOV	WORD PTR [ss:ThisDPB],DI
  1121 0000036F 368C06[0200]            	MOV	WORD PTR [ss:ThisDPB+2],ES
  1122 00000374 C3                      	return
  1123                                  EndProc Splice
  1123          ******************       warning: ***** Possible stack size error in Splice ***** [-w+user]
  1124                                  
  1125                                  Break <$NameTrans - partially process a name>
  1126                                  
  1127                                  ;
  1128                                  ;   $NameTrans - allow users to see what names get mapped to.  This call
  1129                                  ;   performs only string substitution and canonicalization, not splicing.  Due
  1130                                  ;   to Transpath playing games with devices, we need to insure that the output
  1131                                  ;   has drive letter and :  in it.
  1132                                  ;
  1133                                  ;   Inputs:	DS:SI - source string for translation
  1134                                  ;		ES:DI - pointer to buffer
  1135                                  ;   Outputs:
  1136                                  ;	Carry Clear
  1137                                  ;		Buffer at ES:DI is filled in with data
  1138                                  ;		ES:DI point byte after nul byte at end of dest string in buffer
  1139                                  ;	Carry Set
  1140                                  ;		AX = error_path_not_found
  1141                                  ;   Registers modified: all
  1142                                  
  1143                                  Procedure   D_NameTrans,Near
  1143          ******************       warning: proc D_NameTrans... [-w+user]
  1144                                   ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGroup
  1145 00000375 1E560657                	SaveReg <DS,SI,ES,DI>
  1146 00000379 BF[0000]                	MOV	DI,OFFSET OpenBuf wrt DOSGroup
  1147 0000037C E8DEFC                  	CALL	TransPath		; to translation (everything)
  1148 0000037F 5F075E1F                	RestoreReg  <DI,ES,SI,DS>
  1149 00000383 7303                    	JNC	TransOK
  1150 00000385 E9(0000)                	transfer    SYS_Ret_Err
  1151                                  TransOK:
  1152 00000388 BE[0000]                	MOV	SI,OFFSET OpenBuf wrt DOSGroup
  1153 0000038B 161F                    	Context DS
  1154                                  GotText:
  1155 0000038D E8(0000)                	Invoke	FStrCpy
  1156 00000390 E9(0000)                	Transfer    SYS_Ret_OK
  1157                                  EndProc D_NameTrans
  1158                                  
  1159                                  Break	<DriveFromText - return drive number from a text string>
  1160                                  
  1161                                  ;
  1162                                  ;   DriveFromText - examine DS:SI and remove a drive letter, advancing the
  1163                                  ;   pointer.
  1164                                  ;
  1165                                  ;   Inputs:	DS:SI point to a text string
  1166                                  ;   Outputs:	AL has drive number
  1167                                  ;		DS:SI advanced
  1168                                  ;   Registers modified: AX,SI.
  1169                                  
  1170                                  Procedure   DriveFromText,NEAR
  1170          ******************       warning: proc DriveFromText... [-w+user]
  1171                                   ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
  1172 00000393 30C0                    	XOR	AL,AL			;	drive = 0;
  1173 00000395 803C00                  	CMP	BYTE PTR [SI],0 	;	if (*s &&
  1174 00000398 74DA                    	retz
  1175 0000039A 807C013A                	CMP	BYTE PTR [SI+1],':'     ;           s[1] == ':') {
  1176 0000039E 75D4                    	retnz
  1177                                   %IF  DBCS				;AN000;
  1178                                  ;--------------------- Start of DBCS 2/18/KK
  1179                                  	push	ax		       ;AN000;
  1180                                  	mov	al,[si] 	       ;AN000;
  1181                                  	invoke	testkanj	       ;AN000;
  1182                                  	pop	ax		       ;AN000;
  1183                                  	retnz			       ;AN000;
  1184                                  ;--------------------- End of DBCS 2/18/KK
  1185                                   %ENDIF				       ;AN000;
  1186 000003A0 AD                      	LODSW				;	    drive = (*s | 020) - 'a'+1;
  1187 000003A1 3C61                    	cmp al, 'a'
  1188 000003A3 7202                    	jb .nottocaps
  1189 000003A5 2C20                    	sub al, 20h
  1190                                  .nottocaps:
  1191 000003A7 2C40                    	SUB	AL,'A'-1                ;           s += 2;	; CDS limit
  1192 000003A9 75C9                    	retnz
  1193 000003AB B0FF                    	MOV	AL,-1			; nuke AL...
  1194 000003AD C3                      	return				;	    }
  1195                                  EndProc DriveFromText
  1196                                  
  1197                                  Break	<TextFromDrive - convert a drive number to a text string>
  1198                                  
  1199                                  ;
  1200                                  ;   TextFromDrive - turn AL into a drive letter: and put it at es:di with
  1201                                  ;   trailing :. TextFromDrive1 takes a 1-based number.
  1202                                  ;
  1203                                  ;   Inputs:	AL has 0-based drive number
  1204                                  ;   Outputs:	ES:DI advanced
  1205                                  ;   Registers modified: AX
  1206                                  
  1207                                  Procedure TextFromDrive,NEAR
  1207          ******************       warning: proc TextFromDrive... [-w+user]
  1208                                   ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
  1209 000003AE FEC0                    	INC	AL
  1210                                  	Entry	TextFromDrive1
  1211 000003B0 0440                    	ADD	AL,'A'-1                ;   *d++ = drive-1+'A';
  1212 000003B2 B43A                    	MOV	AH,":"                  ;   strcat (d, ":");
  1213 000003B4 AB                      	STOSW
  1214 000003B5 C3                      	return
  1215                                  EndProc TextFromDrive
  1216                                  
  1217                                  Break	<PathPref - see if one path is a prefix of another>
  1218                                  
  1219                                  ;
  1220                                  ;   PathPref - compare DS:SI with ES:DI to see if one is the prefix of the
  1221                                  ;   other.  Remember that only at a pathchar break are we allowed to have a
  1222                                  ;   prefix: A:\ and A:\FOO
  1223                                  ;
  1224                                  ;   Inputs:	DS:SI potential prefix
  1225                                  ;		ES:DI string
  1226                                  ;   Outputs:	Zero set => prefix found
  1227                                  ;		    DI/SI advanced past matching part
  1228                                  ;		Zero reset => no prefix, DS/SI garbage
  1229                                  ;   Registers modified: CX
  1230                                  
  1231                                  Procedure   PathPref,NEAR
  1231          ******************       warning: proc PathPref... [-w+user]
  1232 000003B6 E8(0000)                	Invoke	DStrLen 		; get length
  1233 000003B9 49                      	DEC	CX			; do not include nul byte
  1234                                   %IF  DBCS				;AN000;
  1235                                  ;----------------------- Start of DBCS 2/13/KK
  1236                                  	SaveReg <AX>			;AN000;; save char register
  1237                                  CmpLp:					;AN000;
  1238                                  	MOV	AL,[SI] 		;AN000;
  1239                                  	invoke	Testkanj		;AN000;
  1240                                  	jz	NotKanj9		;AN000;
  1241                                  	CMPSW				;AN000;
  1242                                  	JNZ	Prefix			;AN000;
  1243                                  	DEC	CX			;AN000;
  1244                                  	LOOP	CmpLp			;AN000;
  1245                                  	JMP	SHORT NotSep		;AN000;
  1246                                  NotKanj9:				;AN000;
  1247                                  	CMPSB				;AN000;
  1248                                  	JNZ	Prefix			;AN000;
  1249                                  	LOOP	CmpLp			;AN000;
  1250                                  ;----------------------- End of DBCS 2/13/KK
  1251                                   %ELSE					;AN000;
  1252 000003BA F3A6                    	REPZ	CMPSB			; compare
  1253 000003BC 75F7                    	retnz				; if NZ then return NZ
  1254 000003BE 50                      	SaveReg <AX>			; save char register
  1255                                   %ENDIF					;AN000;
  1256 000003BF 8A44FF                  	MOV	AL,[SI-1]		; get last byte to match
  1257 000003C2 E8(0000)                	Invoke	PathChrCmp		; is it a path char (Root!)
  1258 000003C5 7406                    	JZ	Prefix			; yes, match root (I hope)
  1259                                  NotSep: 				; 2/13/KK
  1260 000003C7 268A05                  	MOV	AL,[ES:DI]		; get next char to match
  1261 000003CA E878FE                  	CALL	PathSepGotCh		; was it a pathchar?
  1262                                  Prefix:
  1263 000003CD 58                      	RestoreReg  <AX>		; get back original
  1264 000003CE C3                      	return
  1265                                  EndProc PathPref
  1266                                  
  1267                                  Break	<ScanPathChar - see if there is a path character in a string>
  1268                                  
  1269                                  ;
  1270                                  ;     ScanPathChar - search through the string (pointed to by DS:SI) for
  1271                                  ;     a path separator.
  1272                                  ;
  1273                                  ;     Input:	DS:SI target string (null terminated)
  1274                                  ;     Output:	Zero set => path separator encountered in string
  1275                                  ;		Zero clear => null encountered
  1276                                  ;     Registers modified: SI
  1277                                  
  1278                                  Procedure     ScanPathChar,NEAR
  1278          ******************       warning: proc ScanPathChar... [-w+user]
  1279 000003CF AC                      	LODSB				; fetch a character
  1280                                   %IF  DBCS				;AN000;
  1281                                  	invoke	TestKanj		;AN000;; 2/13/KK
  1282                                  	jz	NotKanjr		;AN000;; 2/13/KK
  1283                                  	LODSB				;AN000;; 2/13/KK
  1284                                  	OR	AL,AL			;AN000;; 2/13/KK  3/31/removed
  1285                                  	JNZ	ScanPathChar		;AN000;; 2/13/KK  3/31/removed
  1286                                  	INC	AL			;AN000;; 2/13/KK
  1287                                  	return				;AN000;; 2/13/KK
  1288                                  					;AN000;
  1289                                  NotKanjr:				;AN000;; 2/13/KK
  1290                                   %ENDIF					;AN000;
  1291 000003D0 E872FE                  	call	PathSepGotCh
  1292 000003D3 75FA                    	JNZ	ScanPathChar		; not \, / or NUL => go back for more
  1293 000003D5 E8(0000)                	invoke	PathChrCmp		; path separator?
  1294 000003D8 C3                      	return
  1295                                  EndProc       ScanPathChar
  1296                                  
  1297                                  END
