c++windowswinapifilesystems

Unable to make folder readonly


I am trying to make a readonly folder and for that I am using the following code:

#include <windows.h>
#include <iostream>

bool MakeReadonly(const char* folderPath)
{
    DWORD attrs = GetFileAttributesA(folderPath);
    return SetFileAttributesA(folderPath, attrs | FILE_ATTRIBUTE_READONLY) != 0;
}


int main() 
{
    std::string folderPath = "C:\\Users\\Username\\Desktop\\mydir";
    if (MakeReadonly(folderPath.c_str()))
    {
        std::cout << "Folder is readonly now";
    }
}

The MakeReadonly function returns true, but the mydir folder does not become readonly.

However, if you pass a path to a file instead of a folder to the MakeReadonly function, then this file will become readonly. What should be done to make this function work for a folder as well?


Solution

  • You cannot make a directory read-only on windows. As @Yksisarvinen said, the read-only attribute is not honored on directories. If you want to make everything in the folder read-only, you could recursively set all the files in the folder to read-only, but this would not affect new files added to the folder.

    Here is the code that recursively sets all files to read-only within a folder:

    #include <windows.h>
    #include <iostream>
    #include <string>
    
    bool SetReadOnlyRecursive(const char* folderPath) 
    {
        DWORD attrs = GetFileAttributesA(folderPath);
        if (attrs == INVALID_FILE_ATTRIBUTES) {
            std::cerr << "Failed to get attributes for folder: " << folderPath << std::endl;
            return false;
        }
        
        if (!(attrs & FILE_ATTRIBUTE_DIRECTORY)) {
            std::cerr << folderPath << " is not a valid folder." << std::endl;
            return false;
        }
    
        WIN32_FIND_DATA findFileData;
        HANDLE hFind = FindFirstFile((std::string(folderPath) + "\\*").c_str(), &findFileData);
    
        if (hFind == INVALID_HANDLE_VALUE) {
            std::cerr << "Failed to open folder for scanning: " << folderPath << std::endl;
            return false;
        }
    
        do {
            if (std::string(findFileData.cFileName) == "." || std::string(findFileData.cFileName) == "..") {
                continue;
            }
    
            std::string fullPath = std::string(folderPath) + "\\" + findFileData.cFileName;
    
            if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
                if (!SetReadOnlyRecursive(fullPath.c_str())) {
                    FindClose(hFind);
                    return false;
                }
            } 
            else {
                if (!SetFileAttributesA(fullPath.c_str(), findFileData.dwFileAttributes | FILE_ATTRIBUTE_READONLY)) {
                    std::cerr << "Failed to set read-only for file: " << fullPath << std::endl;
                    FindClose(hFind);
                    return false;
                }
            }
        } while (FindNextFile(hFind, &findFileData) != 0);
    
        FindClose(hFind);
        return true;
    }
    
    int main() 
    {
        std::string folderPath = "C:\\Users\\Username\\Desktop\\mydir";
        if (SetReadOnlyRecursive(folderPath.c_str())) {
            std::cout << "Folder and its contents are read-only now." << std::endl;
        } else {
            std::cout << "Failed to set folder to read-only." << std::endl;
        }
    
        return 0;
    }