『第 3 楼』:
 
 
使用 LLM 解释/回答一下
  
	TITLE	DOS_RENAME - Internal RENAME call for MS-DOS 
	NAME	DOS_RENAME 
; 
;	Microsoft Confidential 
;	Copyright (C) Microsoft Corporation 1991 
;	All Rights Reserved. 
; 
 
;**	Low level routine for renaming files 
; 
;	DOS_RENAME 
; 
;	Modification history: 
; 
;	    Created: ARR 30 March 1983 
 
	.xlist 
	.xcref 
	include version.inc 
	include dosseg.inc 
	INCLUDE DOSSYM.INC 
	INCLUDE DEVSYM.INC 
	include sf.inc 
	include find.inc 
	include filemode.inc 
	include mult.inc 
	.cref 
	.list 
 
Installed = TRUE 
 
	i_need	RENAMEDMA,BYTE 
	i_need	AUXSTACK,BYTE 
	i_need	DESTSTART,WORD 
	i_need	DIRSTART,WORD 
	i_need	CURBUF,DWORD 
	I_need	NAME1,BYTE 
	i_need	NAME2,BYTE 
	i_need	WFP_START,WORD 
	i_need	REN_WFP,WORD 
	i_need	CURR_DIR_END,WORD 
	i_need	DMAADD,DWORD 
	i_need	THISCDS,DWORD 
	i_need	THISDPB,DWORD 
	i_need	THISSFT,DWORD 
	i_need	CREATING,BYTE 
	i_need	THISDRV,BYTE 
	i_need	ATTRIB,BYTE 
	i_need	FOUND_DEV,BYTE 
	i_need	FAILERR,BYTE 
	i_need	EXTERR_LOCUS,BYTE 
	i_need	SAVE_BX,WORD 
 
 
DOSCODE	SEGMENT 
	ASSUME	SS<img src="images/smilies/face-smile-big.png" align="absmiddle" border="0">OSDATA,CS<img src="images/smilies/face-smile-big.png" align="absmiddle" border="0">OSCODE 
;---------------------------------------------------------------------------- 
; 
; Procedure Name : DOS_RENAME 
; 
; Inputs: 
;	 Points to SOURCE WFP string ("d:/" must be first 3 
;		chars, NUL terminated) 
;	 Points to end of Current dir part of string  
;		( = -1 if current dir not involved, else 
;		 Points to first char after last "/" of current dir part) 
;	 Points to DEST WFP string ("d:/" must be first 3 
;		chars, NUL terminated) 
;	 Points to CDS being used 
;		(Low word = -1 if NUL CDS (Net direct request)) 
;	 Is attribute of search, determines what files can be found 
; Function: 
;	Rename the specified file(s) 
;	NOTE: This routine uses most of AUXSTACK as a temp buffer. 
; Outputs: 
;	CARRY CLEAR 
;	    OK 
;	CARRY SET 
;	    AX is error code 
;		error_file_not_found 
;			No match for source, or dest path invalid 
;		error_not_same_device 
;			Source and dest are on different devices 
;		error_access_denied 
;			Directory specified (not simple rename), 
;			Device name given, Destination exists. 
;			NOTE: In third case some renames may have 
;			 been done if metas. 
;		error_path_not_found 
;			Bad path (not in curr dir part if present) 
;			SOURCE ONLY 
;		error_bad_curr_dir 
;			Bad path in current directory part of path 
;			SOURCE ONLY 
;		error_sharing_violation 
;			Deny both access required, generates an INT 24. 
; DS preserved, others destroyed 
; 
;---------------------------------------------------------------------------- 
 
	procedure   DOS_RENAME,NEAR 
 
;hkn; DOS_RENAME is called from file.asm and fcbio.asm. DS has been set up 
;hkn; at this point to DOSDATA. 
 
	DOSAssume   ,"DOS_Rename" 
	ASSUME	ES:NOTHING 
 
	Invoke	TestNet 
	JNC	LOCAL_RENAME 
 
IF NOT Installed 
	transfer NET_RENAME 
ELSE 
	MOV	AX,(multNET SHL 8) OR 17 
	INT	2FH 
	return 
ENDIF 
 
LOCAL_RENAME: 
	MOV	,errLOC_Disk 
	MOV	SI, 
	MOV	DI, 
	MOV	AL,BYTE PTR  
	MOV	AH,BYTE PTR  
	OR	AX,2020H		; Lower case 
	CMP	AL,AH 
	JZ	SAMEDRV 
	MOV	AX,error_not_same_device 
	STC 
	return 
 
SAMEDRV: 
	PUSH	WORD PTR  
	PUSH	WORD PTR  
	MOV	WORD PTR ,DS 
 
;hkn; RENAMEDMA is in DOSDATA 
	MOV	WORD PTR ,OFFSET DOSDATA:RENAMEDMA 
	MOV	,0		; Rename fails on DEVS, assume not a dev 
	EnterCrit   critDisk 
	invoke	DOS_SEARCH_FIRST	; Sets  to 1, :BX 
					;    points to entry 
	JNC	Check_Dev 
	CMP	AX,error_no_more_files 
	JNZ	GOTERR 
	MOV	AX,error_file_not_found 
GOTERR: 
	STC 
RENAME_POP: 
	POP	WORD PTR  
	POP	WORD PTR  
	LeaveCrit   critDisk 
	return 
 
Check_dev: 
	MOV	AX,error_access_denied	; Assume error 
 
	PUSH	DS			      ;PTM.				;AN000; 
	LDS	SI,		      ;PTM.  chek if source a dir	;AN000; 
	ADD	SI,find_buf_attr	      ;PTM.				;AN000; 
	TEST	,attr_directory  ;PTM.				;AN000; 
	JZ	notdir			      ;PTM.				;AN000; 
	MOV	SI,		      ;PTM.  if yes, make sure path	;AN000; 
	invoke	Check_Pathlen2		      ;PTM.   length < 67		;AN000; 
notdir: 
	POP	DS			      ;PTM.				;AN000; 
	JA	GOTERR			      ;PTM.				;AN000; 
 
	CMP	,0 
	JNZ	GOTERR 
; At this point a source has been found.  There is search continuation info (a 
; la DOS_SEARCH_NEXT) for the source at RENAMEDMA, together with the first 
; directory entry found. 
; , , and  are set and will remain correct 
; throughout the RENAME since it is known at this point that the source and 
; destination are both on the same device. 
;  is also set. 
	MOV	SI,BX 
	ADD	SI,dir_first 
	invoke	REN_DEL_Check 
	JNC	REN_OK1 
	MOV	AX,error_sharing_violation 
	JMP	RENAME_POP 
 
;------------------------------------------------------------------------------ 
; Check if the source is a file or directory.  If file, delete the entry 
; from the Fastopen cache. If directory, rename it later 
;------------------------------------------------------------------------------ 
REN_OK1:				;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
	PUSH	SI 
	LDS	SI,		      ;BN00X; PTM. chek if source a dir       ;AN000; 
	ADD	SI,find_buf_attr	      ;;BN00XPTM.P5520				   ;AN000; 
	TEST	,attr_directory  ;;BN00XPTM.			      ;AN000; 
	JZ	Not_dir1		      ;;BN00XPTM.			      ;AN000; 
	POP	SI			      ;BN00X 
	JMP	SHORT  SWAP_SOURCE	      ;BN00X 
 
NOT_DIR1:				;;BN00X it is a file, delete the entry 
	POP	SI 
	invoke	FastOpen_Delete 	; delete dir info in fastopen DOS 3.3 
 
SWAP_SOURCE: 
	MOV	AX,		; Swap source and destination 
	MOV	SI,		; Swap source and destination 
	MOV	,SI		; WFP_START = Destination path 
	MOV	,AX		; REN_WFP   = Source path 
	MOV	,-1	; No current dir on dest 
	MOV	WORD PTR ,DIRFREE*256+0ffh  ; Creating, not DEL *.* 
					; A rename is like a CREATE_NEW as far 
					; as the destination is concerned. 
	invoke	GetPathNoSet 
;   If this Getpath fails due to file not found, we know all renames will work 
;   since no files match the destination name.	If it fails for any other 
;   reason, the rename fails on a path not found, or whatever (also fails if 
;   we find a device or directory).  If the Getpath succeeds, we aren't sure 
;   if the rename should fail because we haven't built an explicit name by 
;   substituting for the meta chars in it.  In this case the destination file 
;   spec with metas is in  and the explicit source name is at RENAMEDMA 
;   in the directory entry part. 
	JC	NODEST 
;;	JZ	BAD_ACC 		; Dest string is a directory		;AC000; 
	OR	AH,AH			; Device? 
	JNS	SAVEDEST		; No, continue 
BAD_ACC: 
	MOV	AX,error_access_denied 
	STC 
RENAME_CLEAN: 
	PUSHF				; Save carry state 
	PUSH	AX			; and error code (if carry set) 
	MOV	AL, 
	invoke	FLUSHBUF 
	POP	AX 
	CMP	,0 
	JNZ	BAD_ERR 		; User FAILed to I 24 
	POPF 
	JMP	RENAME_POP 
 
BAD_ERR: 
	POP	AX			; Saved flags 
	MOV	AX,error_path_not_found 
	JMP	GOTERR 
 
NODEST: 
	JNZ	BAD_PATH 
	CMP	,0 
	JNZ	BAD_PATH	; Search for dest failed because user FAILed on 
				;	I 24 
	OR	CL,CL 
	JNZ	SAVEDEST 
BAD_PATH: 
	MOV	AX,error_path_not_found 
	STC 
	JMP	RENAME_POP 
 
SAVEDEST: 
	Context ES 
 
;hkn; NAME1 & NAME2 is in DOSDATA 
	MOV	DI,OFFSET DOSDATA:NAME2 
	MOV	SI,OFFSET DOSDATA:NAME1 
 
	MOV	CX,11 
	REP	MOVSB			; Save dest with metas at NAME2 
	MOV	AX, 
	MOV	,AX 
BUILDDEST: 
	Context ES			; needed due to JMP BUILDDEST below 
 
;hkn; RENAMEDMA, NAME1, NAME2 in DOSDATA 
	MOV	BX,OFFSET DOSDATA:RENAMEDMA + 21   ; Source of replace chars 
	MOV	DI,OFFSET DOSDATA:NAME1    ; Real dest name goes here 
	MOV	SI,OFFSET DOSDATA:NAME2    ; Raw dest 
 
ifdef DBCS 
	mov	cx,8 
	call	new_rename 
	mov	cx,3 
	call	new_rename 
else 
	MOV	CX,11 
	CALL	NEW_RENAME		    ;IFS. replace ? chars		;AN000; 
endif 
 
	MOV	,attr_all	; Stop duplicates with any attributes 
	MOV	,0FFH 
	invoke	DEVNAME 		; Check if we built a device name 
	ASSUME	ES:NOTHING 
	JNC	BAD_ACC 
	MOV	BX, 
	LES	BP, 
	invoke	SetDirSrch		; Reset search to start of dir 
	JC	BAD_ACC 		; Screw up 
	invoke	FINDENTRY		; See if new name already exists 
	JNC	BAD_ACC 		; Error if found 
	CMP	,0 
	JNZ	BAD_ACCJ		; Find failed because user FAILed to I 24 
	MOV	AX,		; DIRSTART of dest 
	CMP	AX,WORD PTR 	; DIRSTART of source 
	JZ	SIMPLE_RENAME		; If =, just give new name 
 
	MOV	AL, 
	TEST	AL,attr_directory 
	JNZ	BAD_ACCJ		; Can only do a simple rename on dirs, 
					; otherwise the .  and ..  entries get 
					; wiped. 
	MOV	,AL 
	MOV	WORD PTR ,DS 
 
;hkn; AUXSTACK is in DOSDATA 
	MOV	SI,OFFSET DOSDATA:AUXSTACK - SIZE SF_ENTRY 
	MOV	WORD PTR ,SI 
	MOV	.sf_mode,sharing_compat+open_for_both 
	XOR	CX,CX			; Set "device ID" for call into makenode 
	invoke	RENAME_MAKE		; This is in mknode 
	JNC	GOT_DEST 
BAD_ACCJ: 
	JMP	BAD_ACC 
 
GOT_DEST: 
	SAVE	 
	LES	DI,ThisSFT		; Rename_make entered this into sharing 
	Invoke	ShareEnd		; we need to remove it. 
	RESTORE  
; A zero length entry with the correct new name has now been made at 
;   :BX. 
	LES	DI, 
	Assert	ISBUF,,"Got_Dest" 
 
	TEST	ES:,buf_dirty  ;LB. if already dirty		;AN000; 
	JNZ	yesdirty		  ;LB.	  don't increment dirty count   ;AN000; 
	invoke	INC_DIRTY_COUNT 	  ;LB.					;AN000; 
	OR	ES:,buf_dirty 
yesdirty: 
	MOV	DI,BX 
	ADD	DI,dir_attr		; Skip name 
 
;hkn; RENAMEDMA is in DOSDATA 
	MOV	SI,OFFSET DOSDATA:RENAMEDMA + 21 + dir_attr 
	MOV	CX,(SIZE dir_entry) - dir_attr 
	REP	MOVSB 
	CALL	GET_SOURCE 
	DLJC	RENAME_OVER 
	MOV	DI,BX 
	MOV	ES,WORD PTR  
	MOV	AL,DIRFREE 
	STOSB				; "free" the source 
	JMP	SHORT DIRTY_IT 
 
SIMPLE_RENAME: 
	CALL	GET_SOURCE		; Get the source back 
	JC	RENAME_OVER 
	MOV	DI,BX 
	MOV	ES,WORD PTR  
 
;hkn; NAME1 is in DOSDATA 
	MOV	SI,OFFSET DOSDATA:NAME1    ; New Name 
	MOV	CX,11 
	REP	MOVSB 
DIRTY_IT: 
	MOV	DI,WORD PTR  
 
	TEST	ES:,buf_dirty  ;LB. if already dirty		;AN000; 
	JNZ	yesdirty2		  ;LB.	  don't increment dirty count   ;AN000; 
	invoke	INC_DIRTY_COUNT 	  ;LB.					;AN000; 
	OR	ES:,buf_dirty 
 
;------------------------------------------------------------------------------ 
; Check if the source is a directory of file.  If directory rename it to the 
; the new name in the Fastopen cache buffer.   If file name it has been 
; previously deleted. 
;------------------------------------------------------------------------------ 
Yesdirty2: 
	PUSH	SI 
	LDS	SI,		      ;;BN00XPTM. chek if source a dir	     ;AN000; 
	ADD	SI,find_buf_attr	      ;;BN00XPTM.P5520				   ;AN000; 
	TEST	,attr_directory  ;;BN00XPTM.			      ;AN000; 
	JZ	Not_dir2		      ;;BN00XPTM.			      ;AN000; 
	INVOKE	FASTOPEN_RENAME 	      ;;BN00X rename dir entry in fastopen 
	POP	SI 
	JMP	SHORT NOT_DIRTY1 
 
NOT_DIR2:				      ;;BN00X it is a file, delete the entry 
	POP	SI 
 
NOT_DIRTY1:				      ;;BN00X 
 
	Assert	ISBUF,,"Dirty_it" 
NEXT_SOURCE: 
 
;hkn; RENAMEDMA is in DOSDATA 
	MOV	SI,OFFSET DOSDATA:RENAMEDMA + 1    ;Name 
; 
; WARNING!  Rename_Next leaves the disk critical section *ALWAYS*.  We need 
; to enter it before going to RENAME_Next. 
; 
	EnterCrit   critDisk 
	MOV	,0	; Correct setting for search (we changed it 
				;   to FF when we made the prev new file). 
	invoke	RENAME_NEXT 
; 
; Note, now, that we have exited the previous ENTER and so are back to where 
; we were before. 
; 
	JC	RENAME_OVER 
	LEA	SI,.dir_First 
	invoke	REN_DEL_Check 
	JNC	REN_OK2 
	MOV	AX,error_sharing_violation 
	JMP	RENAME_CLEAN 
 
;------------------------------------------------------------------------------ 
; Check if file or directory. If file, delete file from the Fastopen cache, 
; if directory, rename directory name in the Fastopen cache. 
;----------------------------------------------------------------------------- 
REN_OK2: 
	MOV	AL,	   ; PTR P5622 
	TEST	AL,attr_directory	;;BN00X directory 
	JZ	Ren_Directory		;;BN00X no - file, delete it 
	INVOKE	FASTOPEN_DELETE 	;;BN00X delete dir info in fastopen DOS 3.3 
	JMP	BUILDDEST		;;BN00X 
 
Ren_Directory: 
	INVOKE	FASTOPEN_RENAME 	;;BN00X delete dir info in fastopen DOS 3.3 
	JMP	BUILDDEST 
 
RENAME_OVER: 
	CLC 
	JMP	RENAME_CLEAN 
;---------------------------------------------------------------------------- 
; 
; Procedure: GET_SOURCE 
; 
; Inputs: 
;	RENAMEDMA has source info 
; Function: 
;	Re-find the source 
; Output: 
;	 set 
;	:BX points to entry 
;	Carry set if error (currently user FAILed to I 24) 
; DS preserved, others destroyed 
;---------------------------------------------------------------------------- 
 
GET_SOURCE: 
	DOSAssume   ,"Get_Source" 
	ASSUME	ES:NOTHING 
 
	MOV	BX,WORD PTR 	; DirStart 
	LES	BP,ThisDPB 
	invoke	SetDirSrch 
	JC	ret_label			; retc 
	invoke	StartSrch 
	MOV	AX,WORD PTR 	; Lastent 
	invoke	GetEnt 
 
ret_label: 
	return 
 
EndProc DOS_RENAME 
 
;---------------------------------------------------------------------------- 
; 
;Procedure: NEW_RENAME 
; 
;Input: DS:SI -> raw string with ? 
;	ES<img src="images/smilies/face-smile-big.png" align="absmiddle" border="0">I -> destination string 
;	DS:BX -> source string 
;Function: replace ? chars of raw string with chars in source string and 
;	   put in destination string 
;Output: ES<img src="images/smilies/face-smile-big.png" align="absmiddle" border="0">I-> new string 
;--------------------------------------------------------------------------- 
 
	ASSUME	ES:NOTHING 
procedure   NEW_RENAME,NEAR 
	DOSAssume   ,"NEW_Rename" 
 
ifdef DBCS				; ### if DBCS ### 
 
	mov	ah,0			; reset DBCS flag 
	mov	dl,cl			; reset counter 
	mov	dh,cl			; save length to do 
newren_loop: 
	cmp	ah,1			; if it was lead byte 
	jz	newren_dbcs 
	mov	ah,0			; reset if it was single or tail byte 
	mov	al,			; get source char 
	invoke	testkanj 
	jz	newren_load		; if not lead byte 
newren_dbcs: 
	inc	ah			; set dbcs flag 
newren_load: 
	lodsb				; get raw char 
	cmp	al,'?' 
	jnz	newren_store		; if not '?' 
	cmp	ah,0 
	jz	newren_conv		; if source is single 
	cmp	ah,1 
	jnz	newren_pass		; if source is not lead 
	cmp	cl,dh 
	jnz	newren_lead		; if this is not 1st char 
	cmp	byte ptr ,' ' 
	jz	newren_double		; if this is the end 
newren_lead: 
	cmp	byte ptr ,'?' 
	jnz	newren_pass		; if no '?' for tail byte 
	cmp	cx,1 
	jbe	newren_pass		; if no room for tail byte 
newren_double: 
	mov	al, 
	stosb 
	dec	dl 
	inc	bx 
	inc	si 
	dec	cx 
newren_conv: 
	mov	al, 
newren_store: 
	stosb				; store in destination 
	dec	dl			; decrese counter 
newren_pass: 
	inc	bx 
	loop	newren_loop 
	mov	cl,dl			; get stored length 
	xor	ch,ch 
	jcxz	newren_ret		; if all done 
	mov	al,' ' 
	rep	stosb			; put sapce 
newren_ret: 
	return 
 
else					; ### if Not DBCS ### 
 
NEWNAM: 
	LODSB 
	CMP	AL,"?" 
	JNZ	NOCHG 
	MOV	AL, 		; Get replace char 
NOCHG: 
	STOSB 
	INC	BX			; Next replace char 
	LOOP	NEWNAM 
	return 
endif					; ### end if Not DBCS ### 
 
EndProc NEW_RENAME 
 
 
DOSCODE	ENDS 
    END 
 
 
    
 
  
 |