Little C++ WIN32 gem



  • DWORD FileAttribs = ::GetFileAttributes(to_path);
    FileAttribs ^= FILE_ATTRIBUTE_READONLY;
    ::SetFileAttributes(to_path, FileAttribs);
    if ( ::CopyFile ( from_path, to_path, FALSE ) )
    {
    ...
    }

     

    Guess what is it supposed to do? :) 

     



  • @tolstick said:

    DWORD FileAttribs = ::GetFileAttributes(to_path);
    FileAttribs ^= FILE_ATTRIBUTE_READONLY;
    ::SetFileAttributes(to_path, FileAttribs);
    if ( ::CopyFile ( from_path, to_path, FALSE ) )
    {
    ...
    }

    Guess what is it supposed to do? :) 

    My guess?

    Open up a file, unset read-only, and write to it.

    Why did they TOGGLE read-only?

     



  • @tolstick said:

    Guess what is it supposed to do? :) 

    Well, instead of removing read-only status, it just toggles it, making the copying quite difficult :-)

    FileAttribs &= ^ FILE_ATTRIBUTE_READONLY; ?? 



  • It uses XOR, so if the file is already read-only, it would make it read-write. However, if the file is already read-write, it would make it read-only.



  • Note that it sets all possible attributes on the file if the call to GetFileAttributes fails: 

    http://blogs.msdn.com/oldnewthing/archive/2003/08/27/54710.aspx

     

    And that should be FileAttribs &= ~FILE_ATTRIBUTE_READONLY;



  • @Nandurius said:

    @tolstick said:
    Guess what is it supposed to do? :) 

    Well, instead of removing read-only status, it just toggles it, making the copying quite difficult :-)

    FileAttribs &= ^ FILE_ATTRIBUTE_READONLY; ?? 

    Sure!

    But one interesting thing is that this code works fine while the source file is RO, and even one more time when the source file is RW, and only after that it fails to copy the new version of file :)



     



  • Looking at the code, I would assume that the intention is to copy a file over another (possibly) existing file. The use of GetFileAttributes / SetFileAttributes would be to ensure that the copy succeeds if the target file exists. The copy will fail if the target file is read-only.

    There are 3 issues here.

    Firstly, if the target file does not exist, GetFileAttributes will return INVALID_FILE_ATTRIBUTES. If this case the call to SetFileAttributes is unnecessary and guaranteed to fail.

    Secondly (as another poster mentioned), the use of ^= will toggle the read-only bit, not unset it. The correct syntax is FileAttribs &= ~(FILE_ATTRIBUTE_READONLY).

    Thirdly, this ignores another file flag that can cause the copy to fail. According to the MSDN documentation: This function fails with ERROR_ACCESS_DENIED if the destination file already exists and has the FILE_ATTRIBUTE_HIDDEN or FILE_ATTRIBUTE_READONLY attribute set. This means that the correct code from above should be FileAttribs &= ~(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY).

     


Log in to reply