Win32 CopyFileEx
and CopyFile2
both have an option flag
COPY_FILE_OPEN_SOURCE_FOR_WRITE
where the docs state:
COPY_FILE_OPEN_SOURCE_FOR_WRITE 0x00000004
The file is copied and the original file is opened for write access.
Now, this sounds straightforward, but when I use this flag and try to copy a file that is already opened with "write lock" by someone else, that is no FILE_SHARE_WRITE, but FILE_SHARE_READ, the file is still being copied!
Here is what ProcMon shows when calling this function. Note that these CreateFile events are from a single call to the CopyFileEx function and I omitted the other CreateFile call to the target file:
(sorry for the cinemascope data)
# Without COPY_FILE_OPEN_SOURCE_FOR_WRITE
CreateFile D:\tmp\cpy.txt SUCCESS Desired Access: Generic Read, Disposition: Open, Options: Sequential Access, Non-Directory File, Open Reparse Point, Attributes: n/a, ShareMode: Read, Delete, AllocationSize: n/a, OpenResult: Opened
CreateFile D:\tmp\cpy.txt SUCCESS Desired Access: Generic Read, Disposition: Open, Options: Sequential Access, Synchronous IO Non-Alert, Non-Directory File, Open Reparse Point, Attributes: n/a, ShareMode: Read, Delete, AllocationSize: n/a, OpenResult: Opened
# With COPY_FILE_OPEN_SOURCE_FOR_WRITE
CreateFile D:\tmp\cpy.txt SUCCESS Desired Access: Generic Read/Write, Disposition: Open, Options: Sequential Access, Non-Directory File, Open Reparse Point, Attributes: n/a, ShareMode: Read, Delete, AllocationSize: n/a, OpenResult: Opened
CreateFile D:\tmp\cpy.txt SUCCESS Desired Access: Generic Read/Write, Disposition: Open, Options: Sequential Access, Synchronous IO Non-Alert, Non-Directory File, Open Reparse Point, Attributes: n/a, ShareMode: Read, Delete, AllocationSize: n/a, OpenResult: Opened
# Without, but file already opened prior by someone else as GENERIC_READ+WRITE + FILE_SHARE_READ (deny write)
CreateFile D:\tmp\cpy.txt SHARING VIOLATION Desired Access: Generic Read, Disposition: Open, Options: Sequential Access, Non-Directory File, Open Reparse Point, Attributes: n/a, ShareMode: Read, Delete, AllocationSize: n/a
CreateFile D:\tmp\cpy.txt SUCCESS Desired Access: Generic Read, Disposition: Open, Options: Sequential Access, Non-Directory File, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened
CreateFile D:\tmp\cpy.txt SUCCESS Desired Access: Generic Read, Disposition: Open, Options: Sequential Access, Synchronous IO Non-Alert, Non-Directory File, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened
# *With*, but file already opened prior by someone else as GENERIC_READ+WRITE + FILE_SHARE_READ (deny write)
CreateFile D:\tmp\cpy.txt SHARING VIOLATION Desired Access: Generic Read/Write, Disposition: Open, Options: Sequential Access, Non-Directory File, Open Reparse Point, Attributes: n/a, ShareMode: Read, Delete, AllocationSize: n/a
CreateFile D:\tmp\cpy.txt SHARING VIOLATION Desired Access: Generic Read, Disposition: Open, Options: Sequential Access, Non-Directory File, Open Reparse Point, Attributes: n/a, ShareMode: Read, Delete, AllocationSize: n/a
CreateFile D:\tmp\cpy.txt SHARING VIOLATION Desired Access: Generic Read/Write, Disposition: Open, Options: Sequential Access, Non-Directory File, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a
CreateFile D:\tmp\cpy.txt SUCCESS Desired Access: Generic Read, Disposition: Open, Options: Sequential Access, Non-Directory File, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened
CreateFile D:\tmp\cpy.txt SUCCESS Desired Access: Generic Read, Disposition: Open, Options: Sequential Access, Synchronous IO Non-Alert, Non-Directory File, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened
As we can see, if noone has access to the file before hand, it is indeed opened with Generic Read/Write
access.
However, if you look at the non-flag case and especially at the case where someone else already opened the file for writing, I fail to see what this flag actually gains:
- Since in both "exclusive" cases, the file is opened with
ShareMode: Read, Delete
(no share write), noone else can open it for writing anyways in both cases. - In both "shared" cases, if someone else already opened it for writing, the function internally falls back to
Desired Access: Generic Read ... ShareMode: Read, Write, Delete
anyways.
So,
- the flag doesn't prevent anyone from opening the file with read access.
- write access is already locked out by ShareMode Read only in the non-flag case
- in case it doesn't work, it silently falls back to the non flag case.
So what'the'heck is this flag supposed to achieve? What is the Use Case?