I want to create a file that is:
- Read-only accessible for all local users.
- Read-write accessible only when application runs with elevated privileges.
I have found Windows-classic-samples here. I modified it a bit, so it gives the creator full access and everyone else GENERIC_READ
:
#include <Accctrl.h>
#include <Aclapi.h>
#include <stdexcept>
#include <filesystem>
#define SCOPE_EXIT_LINE(...) /* Assume ignored. */
void accessImpl(const std::filesystem::path &path, bool readWrite)
{
PACL pAcl = nullptr;
DWORD dwAclSize;
SID_IDENTIFIER_AUTHORITY siaWorld = SECURITY_LOCAL_SID_AUTHORITY;
SID_IDENTIFIER_AUTHORITY siaCreator = SECURITY_CREATOR_SID_AUTHORITY;
PSID pEveryoneSid = nullptr;
PSID pOwnerSid = nullptr;
dwAclSize = sizeof(ACL) + 2 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)) + GetSidLengthRequired(1)
+ GetSidLengthRequired(1);
pAcl = static_cast<PACL>(LocalAlloc(0, dwAclSize));
if(pAcl == nullptr)
{
throw std::runtime_error("Failed to allocate ACL");
}
InitializeAcl(pAcl, dwAclSize, ACL_REVISION);
SCOPE_EXIT_LINE(if(pAcl) LocalFree(pAcl));
AllocateAndInitializeSid(&siaWorld, 1, SECURITY_LOCAL_RID, 0, 0, 0, 0, 0, 0, 0, &pEveryoneSid);
SCOPE_EXIT_LINE(if(pEveryoneSid) FreeSid(pEveryoneSid));
AllocateAndInitializeSid(&siaCreator, 1, SECURITY_CREATOR_OWNER_RID, 0, 0, 0, 0, 0, 0, 0, &pOwnerSid);
if(AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_READ | (readWrite ? GENERIC_WRITE : 0) | GENERIC_EXECUTE, pEveryoneSid)
== 0)
{
throw std::runtime_error("Failed to set AddAccessAllowedAce");
}
if(AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, pOwnerSid) == 0)
{
throw std::runtime_error("Failed to set AddAccessAllowedAce");
}
const auto pSD = static_cast<PSECURITY_DESCRIPTOR>(LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH));
if(pSD == nullptr)
{
throw std::runtime_error("Failed to set LocalAlloc SD");
}
if(InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION) == 0
|| SetSecurityDescriptorDacl(pSD, TRUE, pAcl, FALSE) == 0
|| SetFileSecurityW(path.c_str(), DACL_SECURITY_INFORMATION, pSD) == 0)
{
throw std::runtime_error("Failed to set permissions");
}
}
Then I create the file with elevated privileges. Which seems to create the desired access structure:
But for some reason, writing to the file fails even with elevated privileges. (I tried with PowerShell, NotePad++, etc)
What am I doing wrong?