I have tested it on files with most attributes, archive, read only, hidden, system and it works on all I have tested it with. using the API GetFileAttributes() seems to always get the correct file attribute and it works fine on both a CD/DVD and normal fixed disk.
IF 0 ; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
Build this template with "CONSOLE ASSEMBLE AND LINK"
ENDIF ; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
include \masm32\include\masm32rt.inc
.code
start:
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
call main
inkey
exit
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
main proc
LOCAL hSrc :DWORD ; source file handle
LOCAL hDst :DWORD ; destination file handle
LOCAL pBuffer :DWORD ; buffer pointer
LOCAL bSize :DWORD ; buffer size
LOCAL pCmd :DWORD ; pointer command line
LOCAL bcnt :DWORD
LOCAL flen :DWORD
LOCAL fname[260]:BYTE ; file name buffer
LOCAL pname :DWORD ; file name pointer
LOCAL bRead :DWORD
LOCAL bWritten :DWORD
mov pname, ptr$(fname) ; cast buffer to pointer
mov bSize, 1024*1024*16
mov pCmd, cmd$(1) ; get 1st command line argument
fn NameFromPath,pCmd,pname ; get the bare file name
mov pBuffer, alloc(bSize)
; --------------------------------------------------
; open the source file using its own file attributes
; --------------------------------------------------
invoke CreateFile,pCmd,GENERIC_READ,NULL,NULL,OPEN_EXISTING,
rv(GetFileAttributes,pCmd),NULL
mov hSrc, eax
mov hDst, fcreate(pname) ; create the destination file
mov flen, fsize(hSrc)
mov bcnt, 0 ; zero the byte counter
; -------------------------------------------------------
cplp:
mov bRead, fread(hSrc,pBuffer,bSize)
mov bWritten, fwrite(hDst,pBuffer,bRead)
print "."
mov eax, bWritten
add bcnt, eax
mov eax, flen
cmp bcnt, eax
jb cplp
; -------------------------------------------------------
print chr$(13,10)
print "Bytes copied = "
print ustr$(bcnt),13,10
free pBuffer
fclose hSrc
fclose hDst
ret
main endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
end start
No need for attributes when opening an existing file
Quote from: MSDN
When opening an existing file (dwCreationDisposition set to either OPEN_EXISTING, OPEN_ALWAYS, or TRUNCATE_EXISTING), the CreateFile function performs the following actions:
•Checks current file attributes and security settings for requested access, failing if denied.
•Combines the file flags (FILE_FLAG_*) specified by dwFlagsAndAttributes with existing file attributes, and ignores any file attributes (FILE_ATTRIBUTE_*) specified by dwFlagsAndAttributes.
Thanks, I will have to have a play with that to see if it does everything.
:biggrin:
Yep, works fine. Typical over-engineering I guess. :P
Here is the new improved version, it seems to work on all file types I have tested on any readable media so I put the process into its own procedure.
IF 0 ; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
Build this template with "CONSOLE ASSEMBLE AND LINK"
ENDIF ; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
include \masm32\include\masm32rt.inc
block_copy PROTO :DWORD,:DWORD,:DWORD
.code
start:
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
call main
inkey
exit
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
main proc
LOCAL bSize :DWORD ; buffer size
LOCAL pCmd :DWORD ; pointer command line
LOCAL bcnt :DWORD ; procedure return value
LOCAL fname[260]:BYTE ; file name buffer
LOCAL pname :DWORD ; file name pointer
mov pname, ptr$(fname) ; cast buffer to pointer
mov bSize, 1024*1024*16 ; set the block size
mov pCmd, cmd$(1) ; get 1st command line argument
fn NameFromPath,pCmd,pname ; get the bare file name
; ------------------
; call the procedure
; ------------------
mov bcnt, rv(block_copy,pCmd,pname,bSize)
print chr$(13,10)
print "Bytes copied = "
print ustr$(bcnt),13,10
ret
main endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
block_copy proc psrc:DWORD,pdst:DWORD,bsize:DWORD
; arguments --------------------------------------
; psrc = the source file name address
; pdst = the destination file name address
; bsize = the memory buffer size in bytes
; ------------------------------------------------
LOCAL hSrc :DWORD
LOCAL hDst :DWORD
LOCAL pBuf :DWORD
LOCAL bWrt :DWORD
LOCAL bRed :DWORD
LOCAL flen :DWORD
LOCAL bcnt :DWORD
mov pBuf, rv(GlobalAlloc,GMEM_FIXED,bsize)
mov hSrc, rv(CreateFile,psrc,GENERIC_READ,NULL,NULL,OPEN_EXISTING,NULL,NULL)
mov hDst, rv(CreateFile,pdst,GENERIC_WRITE,NULL,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL)
mov flen, rv(GetFileSize,hSrc,NULL)
mov bcnt, 0
cplp:
fn ReadFile,hSrc,pBuf,bsize,ADDR bRed,NULL
; ---------------------------------------------------------
; perform any memory modification here.
; memory address = pBuf
; byte count = bRed
; ---------------------------------------------------------
fn WriteFile,hDst,pBuf,bRed,ADDR bWrt,NULL
print "."
mov eax, bWrt
add bcnt, eax
mov eax, flen
cmp bcnt, eax
jb cplp
fn CloseHandle,hSrc
fn CloseHandle,hDst
fn GlobalFree,pBuf
mov eax, bcnt
ret
block_copy endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
end start