Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

396 lines
9.0 KiB

;****************************************************************************
;* *
;* WFFILE.ASM - *
;* *
;* File Copy Utility Routines *
;* *
;****************************************************************************
include cmacros.inc
include windows.inc
externFP GlobalFree
externFP GlobalAlloc
externFP DosFindFirst
externFP DOS3Call
externFP WFQueryAbort
;*--------------------------------------------------------------------------*
createSeg _%SEGNAME, %SEGNAME, WORD, PUBLIC, CODE
sBegin %SEGNAME
assumes cs,%SEGNAME
assumes ds,DATA
;*--------------------------------------------------------------------------*
;* *
;* IsSerialDevice() - *
;* *
;*--------------------------------------------------------------------------*
; Determines if a handle is a serial or block device file
cProc IsSerialDevice, <PUBLIC,NEAR>
parmW hFile
cBegin
mov ax,4400h ; IOCTL
mov bx,hFile ; Get Device Information about handle
cCall DOS3Call
jnc ISDNoErr
sub ax,ax ; If error, assume false
ISDNoErr:
and ax,0080h ; Extract the character/block bit
cEnd
;*--------------------------------------------------------------------------*
;* *
;* IsDirectory() - *
;* *
;*--------------------------------------------------------------------------*
; Returns TRUE if the specified path points to a directory.
cProc IsDirectory, <PUBLIC,NEAR>
parmW pPath
cBegin
mov ax, 4300h
mov dx, pPath
call DOS3CALL
jc IDNoDir
mov ax, cx ;; for PCNFS
and ax, 10h ; check dir bit
jmp short IDExit
IDNoDir:
sub ax,ax ; Return FALSE
IDExit:
cEnd
;*--------------------------------------------------------------------------*
;* *
;* FileCopy() - *
;* *
;*--------------------------------------------------------------------------*
; Copies one file to another. Assumes that both filespecs are unambiguous.
cProc FileCopy, <PUBLIC,FAR>, <SI,DI>
parmW pszSource ; Source filename
parmW pszDestination ; Destination filename
localW segBuffer ; Buffer segment
localW cbBuffer ; Length of buffer segment
localW hFrom
localW hTo
localB bWhich
localB fFreeBuffer
cBegin
sub ax,ax
mov bWhich,al
mov fFreeBuffer,al ; Initialize various thangs
inc fFreeBuffer ; Remember to blow away the buffer
mov cbBuffer,32768 ; Start at 32K
cf_allocbuf:
mov ax,GMEM_FIXED
push ax
sub ax,ax
push ax
push cbBuffer
cCall GlobalAlloc ; Alloc the buffer for copying
or ax,ax
jnz cf_havememory ; Did we get it?
cmp cbBuffer,1024
jbe cf_oom ; If not, was it the minimum size?
shr cbBuffer,1 ; Try a smaller buffer
jmp short cf_allocbuf
cf_oom:
mov ax,8 ; DOS code for insufficient memory
jmp cf_exit ; return it to the caller
cf_havememory:
mov segBuffer,ax
cf_dontalloc:
mov dx, pszSource ; DS:DX -> filename
mov ax, 3D00h ; open for read NO SHARE!
cCall DOS3Call
jnc cf_sourceopened
jmp_cf_fromerror:
jmp cf_exit
cf_sourceopened:
mov hFrom,ax
mov bx, ax
mov dx, 20h ; RAW mode
mov ax, 4401h ; IOCTL
cCall DOS3Call
;; assume this worked
mov bWhich,40h ; error codes from destination
;; match ERRORONDEST in winfile.h
mov dx,pszDestination
mov ax,3D21h ; create the output file (deny write)
cCall DOS3Call
jnc cf_havedest
cmp ax, 2 ; did we get file not found?
jz cf_try_create
cmp ax, 5 ; did we get access denied?
jz cf_try_create
jmp cf_toerror
cf_try_create:
mov dx, pszDestination ; FNF, create it
mov ah, 3Ch
mov cx,0 ; create normal file
cCall DOS3Call
jc cf_toerror
cf_havedest:
mov hTo,ax ; save handle
mov bx, ax
mov dx, 20h ; RAW mode
mov ax, 4401h ; IOCTL
cCall DOS3Call
;; assume this worked
cf_begincopy:
cf_copyloop:
cCall WFQueryAbort ; yield, allow abort
or ax,ax
jz cf_not_abort
mov ax, 18h ;; DE_OPCANCELLED from winfile.h
jmp short cf_closetoerror
cf_not_abort:
sub dx,dx
push ds
mov ds,segBuffer ; point ds:dx at buffer
mov bWhich,0 ; error from source file
mov cx, cbBuffer
mov bx, hFrom
mov ah, 3Fh ; read from source
cCall DOS3Call
pop ds
jc cf_closetoerror
or ax,ax
jz cf_finished
mov bWhich,40h ; error from destination file
;; match ERRORONDEST in winfile.h
push ds
mov ds,segBuffer
mov cx, ax ; count of bytes to write
mov ah, 40h
mov bx, hTo ; write buffer back out to destination file
cCall DOS3Call
pop ds
jc cf_closetoerror ; error: close files
cmp ax,cx
jz cf_copiedenough ; copied the right number of bytes?
if 0
mov bx,ax ; ds:bx -> first unwritten character
cmp byte ptr [bx],26 ; is it the end of file character?
jnz cf_outofdisk ; nope, must be an error
cCall IsSerialDevice,<hTo> ; is it a serial device?
or ax,ax ; (dx trashed, but that's ok here)
jnz cf_finished ; yes... copy went ok
endif
cf_outofdisk:
mov ax, 13h ;; randomly chosen error code for 'no space'
cf_closetoerror:
push ax
mov bx,hTo ; close the destination file
mov ah,3Eh
cCall DOS3Call
mov dx, pszDestination
mov ah, 41h ; delete the partial destination file
cCall DOS3Call
pop ax
cf_toerror:
or al,bWhich ; indicate which file encountered error
cf_closefromerror:
push ax
mov bx,hFrom
mov ah,3Eh ; close the input file
cCall DOS3Call
pop ax ; return original error
jmp short cf_exit
cf_copiedenough:
cmp ax,cbBuffer ; at end if <cbBuffer
jnz @f
jmp cf_copyloop
@@:
cf_finished:
mov bx, hTo ; truncate the output file
mov ah, 40h
sub cx, cx
cCall DOS3Call
cCall IsSerialDevice,<hTo>
or ax,ax
jnz cf_dontsettime
cCall IsSerialDevice,<hFrom>
or ax, ax
jnz cf_dontsettime
mov ax, 5700h ; for disk files, set the timestamp
mov bx, hFrom
cCall DOS3Call
jc cf_dontsettime
mov ax, 5701h
mov bx, hTo
cCall DOS3Call
cf_dontsettime:
mov bx,hFrom ; close the input file
mov ah,3Eh
cCall DOS3Call
mov bx,hTo ; close the output file
mov ah,3Eh
cCall DOS3Call
xor ax,ax ; error code = 0 => no error
jmp short cf_exit
cf_exit:
cmp fFreeBuffer,0
jz cf_nofreeexit ; need to free buffer?
push ax
push segBuffer
cCall GlobalFree ; get rid o' the thang
pop ax
cf_nofreeexit:
cEnd
;*--------------------------------------------------------------------------*
;* *
;* FileMove() - *
;* *
;*--------------------------------------------------------------------------*
; Moves a file from one place to another on the same device.
; Assumes both paths are unambiguous.
cProc FileMove, <FAR, PUBLIC>, <DI>
parmW pFrom
parmW pTo
cBegin
push ds
pop es
mov dx,pFrom
mov di,pTo
mov ah,56h ; DOS move
cCall DOS3Call
jc fm_exit
sub ax,ax ; Return 0 for success
fm_exit:
cEnd
;*--------------------------------------------------------------------------*
;* *
;* FileRemove() - *
;* *
;*--------------------------------------------------------------------------*
; Removes a file. Assumes the filespec is unambiguous.
cProc FileRemove, <FAR, PUBLIC>
parmW pSpec
cBegin
mov dx,pSpec
mov ah,41h
cCall DOS3Call
jc fr_exit
sub ax,ax ; Return 0 for success
fr_exit:
cEnd
;*--------------------------------------------------------------------------*
;* *
;* MKDir() - *
;* *
;*--------------------------------------------------------------------------*
; Creates a subdirectory
cProc MKDir, <FAR, PUBLIC>
parmW pName
cBegin
mov dx,pName
mov ah,39h
cCall DOS3Call
jc md_exit
sub ax,ax ; Return 0 for success
md_exit:
cEnd
;*--------------------------------------------------------------------------*
;* *
;* RMDir() - *
;* *
;*--------------------------------------------------------------------------*
; Removes a subdirectory
cProc RMDir, <FAR, PUBLIC>
parmW pName
cBegin
mov dx,pName
mov ah,3Ah
cCall DOS3Call
jc rd_exit
sub ax,ax
rd_exit:
cEnd
sEnd
end