page ,132 ;/* ; * Microsoft Confidential ; * Copyright (C) Microsoft Corporation 1991 ; * All Rights Reserved. ; */ ; ; Revision History ; ================ ; ;M031 SR 10/11/90 Bug #3069. Use deny write sharing mode to open files ; instead of compatibility mode. This gives lesser ; sharing violations when files are opened for read on ; a copy operation. ; ; .xlist .xcref include comsw.asm include dossym.inc include syscall.inc include sf.inc include comseg.asm include comequ.asm .list .cref TRANDATA segment public byte extrn FulDir_Ptr:word ;AN052; TRANDATA ends TRANSPACE segment public byte extrn Ascii:byte extrn Binary:byte extrn Concat:byte extrn DestBuf:byte extrn DestFcb:byte extrn DestInfo:byte extrn DestIsDir:byte extrn DestTail:word extrn DestVars:byte extrn DirBuf:byte extrn DirChar:byte extrn FirstDest:byte extrn Inexact:byte extrn MelCopy:byte extrn NxtAdd:word extrn Plus:byte extrn SDirBuf:byte extrn SrcInfo:byte extrn SrcXName:byte extrn Tpa:word extrn TrgXName:byte extrn UserDir1:byte TRANSPACE ends TRANCODE segment public byte extrn BadPath_Err:near ;AN022; extrn CopErr:near ;AN052; extrn Extend_Setup:near ;AN022; public BuildPath public SetStars public SetAsc ASSUME cs:TRANGROUP,ds:TRANGROUP,es:TRANGROUP,ss:NOTHING ;*** SetAsc - set Ascii, Binary, Inexact flags based on switches ; ; Given switch vector in AX, ; Set Ascii flag if /a is set ; Clear Ascii flag if /b is set ; Binary set if /b specified ; Leave Ascii unchanged if neither or both are set ; Also sets Inexact if Ascii is ever set. ; AL = Ascii on exit, flags set ; SetAsc: and al,SWITCHA+SWITCHB ; AL = /a, /b flags jpe LoadSw ; even parity - both or neither push ax and al,SWITCHB mov Binary,al pop ax and al,SWITCHA mov Ascii,al or Inexact,al LoadSw: mov al,Ascii or al,al return ;*** BuildDest public BuildDest BuildDest: cmp DestIsDir,-1 jne KnowAboutDest ; figuring already done mov di,offset TRANGROUP:UserDir1 mov bp,offset TRANGROUP:DestVars call BuildPath invoke RestUDir1 ; We now know all about the destination. KnowAboutDest: xor al,al xchg al,FirstDest or al,al jnz FirstDst jmp NotFirstDest FirstDst: ; Create an fcb of the original dest. mov si,DestTail mov di,offset TRANGROUP:DestFcb mov ax,PARSE_FILE_DESCRIPTOR shl 8 int 21h cmp byte ptr [si],0 je GoodParse ;AD052; mov byte ptr [di+1],"|" ; must be illegal file name character mov dx,offset TRANGROUP:FulDir_Ptr ;AN052; issue "file creation error" jmp CopErr ;AN052; GoodParse: mov ax,word ptr DestBuf ; AX = possible "d:" cmp ah,':' je @f mov al,'@' @@: ; AX = "d:" for following FCB drive computation mov cl,Ascii ; CL = saved Ascii flag or al,20h sub al,60h mov DestFcb,al ; store drive # in FCB ;* Figure out what copy mode we're in. ; Letters stand for unambiguous, * for ambiguous pathnames. ; +n stands for additional sources delimited by +'s. ; ; copy a b not concatenating ; copy a * not concatenating ; copy * a concatenating ; copy * * not concatenating ; copy a+n b concatenating ; copy *+n a concatenating ; copy *+n * concatenating, Mel Hallorman style ; Bugbug: copy *.a+a.b *.t picks up only 1st *.a file.. Why? ; copy a.b+*.a *.t picks up all *.a files. mov al,DestInfo ; AL = destination CParse flags mov ah,SrcInfo ; AH = source CParse flags and ax,0202h ; AH,AL = source,dest wildcard flags or al,al jz NotMelCopy ; no destination wildcard ; Destination is wildcarded. cmp al,ah jne NotMelCopy ; no source wildcard ; Source and destination are both wildcarded. cmp Plus,0 je NotMelCopy ; no +'s in source ; Source and destination are wildcarded, and source includes +'s. ; It's Mel Hallorman copy time. inc MelCopy ; 'Mel copy' = true xor al,al jmp short SetConc NotMelCopy: xor al,2 ; AL=0 -> ambiguous destination, 2 otherwise and al,ah shr al,1 ; AL=1 -> ambiguous source, unambiguous dest ; (implies concatenation) SetConc: or al,Plus ; "+" always infers concatenation ; Whew. AL = 1 if concatenating, 0 if not. mov Concat,al shl al,1 shl al,1 mov Inexact,al ; concatenation -> inexact copy cmp Binary,0 jne NotFirstDest ; explicit binary copy mov Ascii,al ; otherwise, concatenate in ascii mode or cl,cl jnz NotFirstDest ; Ascii flag set before, data read correctly or al,al jz NotFirstDest ; Ascii flag did not change state ; At this point there may already be binary read data in the read ; buffer. We need to find the first ^Z (if there is one) and trim the ; amount of data in the buffer correctly. mov cx,NxtAdd jcxz NotFirstDest ; no data, everything ok mov al,1Ah push es xor di,di mov es,Tpa repne scasb ; scan for EOF pop es jne NotFirstDest ; no ^z in buffer, everything ok dec di ; point at ^z mov NxtAdd,di ; new buffer length NOTFIRSTDEST: mov bx,offset trangroup:DIRBUF+1 ; Source of replacement chars cmp CONCAT,0 jz GOTCHRSRC ; Not a concat mov bx,offset trangroup:SDIRBUF+1 ; Source of replacement chars GOTCHRSRC: mov si,offset trangroup:DESTFCB+1 ; Original dest name mov di,DESTTAIL ; Where to put result public buildname BUILDNAME: ifdef DBCS ; ### if DBCS ### mov cx,8 call make_name cmp byte ptr [si],' ' jz @f ; if no extention mov al,dot_chr stosb mov cx,3 call make_name @@: xor al,al stosb ; nul terminate return else ; ### if Not DBCS ### mov cx,8 BUILDMAIN: lodsb cmp al,'?' jnz NOTAMBIG mov al,byte ptr [BX] NOTAMBIG: cmp al,' ' jz NOSTORE stosb NOSTORE: inc bx loop BUILDMAIN mov cl,3 mov al,' ' cmp byte ptr [SI],al jz ENDDEST ; No extension mov al,dot_chr stosb BUILDEXT: lodsb cmp al,'?' jnz NOTAMBIGE mov al,byte ptr [BX] NOTAMBIGE: cmp al,' ' jz NOSTOREE stosb NOSTOREE: inc bx loop BUILDEXT ENDDEST: xor al,al stosb ; NUL terminate return endif ; ### end if Not DBCS ### ifdef DBCS ; ### if DBCS ### make_name: mov ah,0 ; reset DBCS flag mov dh,cl ; save length to do mkname_loop: cmp ah,1 ; if it was lead byte jz mkname_dbcs mov ah,0 ; reset if it was single or tail byte mov al,[bx] ; get source char invoke testkanj jz mkname_load ; if not lead byte mkname_dbcs: inc ah ; set dbcs flag mkname_load: lodsb ; get raw char cmp al,'?' jnz mkname_store ; if not '?' cmp ah,0 jz mkname_conv ; if source is single cmp ah,1 jnz mkname_pass ; if source is not lead cmp cl,dh jnz mkname_lead ; if this is not 1st char cmp byte ptr [si],' ' jz mkname_double ; if this is the end mkname_lead: cmp byte ptr [si],'?' jnz mkname_pass ; if no '?' for tail byte cmp cx,1 jbe mkname_pass ; if no room for tail byte mkname_double: mov al,[bx] stosb inc bx inc si dec cx inc ah ; tail byte will be loaded mkname_conv: mov al,[bx] mkname_store: cmp al,' ' jz mkname_pass stosb ; store in destination mkname_pass: inc bx loop mkname_loop return endif ; ### end if DBCS ### BUILDPATH: test [BP.INFO],2 jnz NOTPFILE ; If ambig don't bother with open mov dx,bp add dx,BUF ; Set DX to spec push di ;AN000; MOV AX,EXTOPEN SHL 8 ;AC000; open the file mov bx,DENY_NONE or READ_OPEN_MODE ; open mode for COPY ;M046 xor cx,cx ;AN000; no special files mov si,dx ;AN030; get file name offset mov dx,read_open_flag ;AN000; set up open flags INT 21h pop di ;AN000; jnc pure_file ;AN022; is pure file invoke get_ext_error_number ;AN022; get the extended error cmp ax,error_file_not_found ;AN022; if file not found - okay jz notpfile ;AN022; cmp ax,error_path_not_found ;AN022; if path not found - okay jz notpfile ;AN022; cmp ax,error_access_denied ;AN022; if access denied - okay jz notpfile ;AN022; jmp extend_setup ;AN022; exit with error pure_file: mov bx,ax ; Is pure file mov ax,IOCTL SHL 8 INT 21h mov ah,CLOSE INT 21h test dl,devid_ISDEV jnz ISADEV ; If device, done test [BP.INFO],4 jz ISSIMPFILE ; If no path seps, done NOTPFILE: mov dx,word ptr [BP.BUF] cmp dl,0 ;AN034; If no drive specified, get jz set_drive_spec ;AN034; default drive dir cmp dh,':' jz DRVSPEC5 set_drive_spec: ;AN034; mov dl,'@' DRVSPEC5: or dl,20h sub dl,60h ; A = 1 invoke SAVUDIR1 jnc curdir_ok ;AN022; if error - exit invoke get_ext_error_number ;AN022; get the extended error jmp extend_setup ;AN022; exit with error curdir_ok: ;AN022; mov dx,bp add dx,BUF ; Set DX for upcomming CHDIRs mov bh,[BP.INFO] and bh,6 cmp bh,6 ; Ambig and path ? jnz CHECKAMB ; jmp if no mov si,[BP.TTAIL] mov bl,':' cmp byte ptr [si-2],bl jnz KNOWNOTSPEC mov [BP.ISDIR],2 ; Know is d:/file jmp short DOPCDJ KNOWNOTSPEC: mov [BP.ISDIR],1 ; Know is path/file dec si ; Point to the / DOPCDJ: jmp DOPCD ;AC022; need long jump CHECKAMB: cmp bh,2 jnz CHECKCD ISSIMPFILE: ISADEV: mov [BP.ISDIR],0 ; Know is file since ambig but no path return CHECKCD: invoke SETREST1 mov ah,CHDIR INT 21h jc NOTPDIR mov di,dx xor ax,ax mov cx,ax dec cx Kloop: ;AN000; 3/3/KK MOV AL,ES:[DI] ;AN000; 3/3/KK INC DI ;AN000; 3/3/KK OR AL,AL ;AN000; 3/3/KK JZ Done ;AN000; 3/3/KK xor ah,ah ;AN000; 3/3/KK invoke Testkanj ;AN000; 3/3/KK JZ Kloop ;AN000; 3/3/KK INC DI ;AN000; 3/3/KK INC AH ;AN000; 3/3/KK jmp Kloop ;AN000; 3/3/KK Done: ;AN000; 3/3/KK dec di mov al,DIRCHAR mov [bp.ISDIR],2 ; assume d:/file OR AH, AH ;AN000; 3/3/KK JNZ Store_pchar ;AN000; 3/3/KK this is the trailing byte of ECS code cmp al,[di-1] jz GOTSRCSLSH Store_pchar: ;AN000; 3/3/KK stosb mov [bp.ISDIR],1 ; know path/file GOTSRCSLSH: or [bp.INFO],6 call SETSTARS return NOTPDIR: invoke get_ext_error_number ;AN022; get the extended error cmp ax,error_path_not_found ;AN022; if path not found - okay jz notpdir_try ;AN022; cmp ax,error_access_denied ;AN022; if access denied - okay jnz extend_setupj ;AN022; otherwise - exit error notpdir_try: ;AN022; mov [bp.ISDIR],0 ; assume pure file mov bh,[bp.INFO] test bh,4 retz ; Know pure file, no path seps mov [bp.ISDIR],2 ; assume d:/file mov si,[bp.TTAIL] cmp byte ptr [si],0 jz BADCDERRJ2 ; Trailing '/' mov bl,dot_chr cmp byte ptr [si],bl jz BADCDERRJ2 ; If . or .. pure cd should have worked mov bl,':' cmp byte ptr [si-2],bl jz DOPCD ; Know d:/file mov [bp.ISDIR],1 ; Know path/file dec si ; Point at last '/' DOPCD: xor bl,bl xchg bl,[SI] ; Stick in a NUL invoke SETREST1 CMP DX,SI ;AN000; 3/3/KK JAE LookBack ;AN000; 3/3/KK PUSH SI ;AN000; 3/3/KK PUSH CX ;AN000; 3/3/KK MOV CX,SI ;AN000; 3/3/KK MOV SI,DX ;AN000; 3/3/KK Kloop2: ;AN000; 3/3/KK LODSB ;AN000; 3/3/KK invoke TestKanj ;AN000; 3/3/KK jz NotKanj4 ;AN000; 3/3/KK LODSB ;AN000; 3/3/KK CMP SI,CX ;AN000; 3/3/KK JB Kloop2 ;AN000; 3/3/KK POP CX ;AN000; 3/3/KK POP SI ;AN000; 3/3/KK JMP SHORT DoCdr ;AN000; 3/3/KK Last char is ECS code, don't check for ; trailing path sep NotKanj4: ;AN000; 3/3/KK CMP SI,CX ;AN000; 3/3/KK JB Kloop2 ;AN000; 3/3/KK POP CX ;AN000; 3/3/KK POP SI ;AN000; 3/3/KK LookBack: ;AN000; 3/3/KK CMP BL,[SI-1] ; if double slash, then complain. JZ BadCDErrJ2 DoCdr: ;AN000; 3/3/KK mov ah,CHDIR INT 21h xchg bl,[SI] retnc invoke get_ext_error_number ;AN022; get the extended error EXTEND_SETUPJ: ;AN022; JMP EXTEND_SETUP ;AN022; go issue the error message BADCDERRJ2: jmp badpath_err ;AC022; go issue path not found message SETSTARS: mov [bp.TTAIL],DI add [bp.SIZ],12 mov ax,dot_qmark mov cx,8 rep stosb xchg al,ah stosb xchg al,ah mov cl,3 rep stosb xor al,al stosb return PUBLIC CompName COMPNAME: mov si,offset trangroup:DESTBUF ;g do name translate of target mov di,offset trangroup:TRGXNAME ;g save for name comparison mov ah,xnametrans ;g int 21h ;g MOV si,offset trangroup:SRCXNAME ;g get name translate of source MOV di,offset trangroup:TRGXNAME ;g get name translate of target invoke STRCOMP return TRANCODE ENDS END