ファイルのセキュリティ記述子に含まれるグループ名またはユーザー名をまとめて取得するコードです。実際には個々のACEから名前を取得して、それをstd::set
でまとめています。
#include <array> #include <string> #include <set> #include <vector> #define STRICT #define NOMINMAX #include <Windows.h> std::wstring GetWindowsDirectoryW() { auto len = ::GetWindowsDirectoryW(nullptr, 0); if (len == 0) return {}; std::wstring s(len - 1, L'\0'); if (::GetWindowsDirectoryW(s.data(), len) == 0) return {}; return s; } std::vector<BYTE> GetFileSecurityW( std::wstring_view filename, SECURITY_INFORMATION requestedInformation) { DWORD needSize; if (!::GetFileSecurityW( filename.data(), requestedInformation, nullptr, 0, &needSize)) { if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER) return {}; } std::vector<BYTE> v(needSize); if (!::GetFileSecurityW( filename.data(), requestedInformation, v.data(), needSize, &needSize)) { return {}; } return v; } struct LookupAccountSidWResult { std::wstring name; std::wstring referenceDomainName; SID_NAME_USE use; }; LookupAccountSidWResult LookupAccountSidW( PSID psid, std::wstring_view systemName = {}) { DWORD nameLen{}; DWORD refDomainNameLen{}; SID_NAME_USE use; if (!::LookupAccountSidW(systemName.data(), psid, nullptr, &nameLen, nullptr, &refDomainNameLen, &use)) { if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER) return {}; } std::wstring name(nameLen - 1, L'\0'); std::wstring refDomainName(refDomainNameLen - 1, L'\0'); if (!::LookupAccountSidW(systemName.data(), psid, name.data(), &nameLen, refDomainName.data(), &refDomainNameLen, &use)) { return {}; } return LookupAccountSidWResult(std::move(name), std::move(refDomainName), use); } PSID GetAceSid(PACE_HEADER pheader) { auto pv{static_cast<PVOID>(pheader)}; switch (pheader->AceType) { case ACCESS_ALLOWED_ACE_TYPE: return &static_cast<PACCESS_ALLOWED_ACE>(pv)->SidStart; case ACCESS_DENIED_ACE_TYPE: return &static_cast<PACCESS_DENIED_ACE>(pv)->SidStart; case SYSTEM_AUDIT_ACE_TYPE: return &static_cast<PSYSTEM_AUDIT_ACE>(pv)->SidStart; case SYSTEM_ALARM_ACE_TYPE: return &static_cast<PSYSTEM_ALARM_ACE>(pv)->SidStart; case ACCESS_ALLOWED_COMPOUND_ACE_TYPE: return nullptr; case ACCESS_ALLOWED_OBJECT_ACE_TYPE: return &static_cast<PACCESS_ALLOWED_OBJECT_ACE>(pv)->SidStart; case ACCESS_DENIED_OBJECT_ACE_TYPE: return &static_cast<PACCESS_DENIED_OBJECT_ACE>(pv)->SidStart; case SYSTEM_AUDIT_OBJECT_ACE_TYPE: return &static_cast<PSYSTEM_AUDIT_OBJECT_ACE>(pv)->SidStart; case SYSTEM_ALARM_OBJECT_ACE_TYPE: return &static_cast<PSYSTEM_ALARM_OBJECT_ACE>(pv)->SidStart; case ACCESS_ALLOWED_CALLBACK_ACE_TYPE: return &static_cast<PACCESS_ALLOWED_CALLBACK_ACE>(pv)->SidStart; case ACCESS_DENIED_CALLBACK_ACE_TYPE: return &static_cast<PACCESS_DENIED_CALLBACK_ACE>(pv)->SidStart; case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE: return &static_cast<PACCESS_ALLOWED_CALLBACK_OBJECT_ACE>(pv)->SidStart; case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE: return &static_cast<PACCESS_DENIED_CALLBACK_OBJECT_ACE>(pv)->SidStart; case SYSTEM_AUDIT_CALLBACK_ACE_TYPE: return &static_cast<PSYSTEM_AUDIT_CALLBACK_ACE>(pv)->SidStart; case SYSTEM_ALARM_CALLBACK_ACE_TYPE: return &static_cast<PSYSTEM_ALARM_CALLBACK_ACE>(pv)->SidStart; case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE: return &static_cast<PSYSTEM_AUDIT_CALLBACK_OBJECT_ACE>(pv)->SidStart; case SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE: return &static_cast<PSYSTEM_ALARM_CALLBACK_OBJECT_ACE>(pv)->SidStart; case SYSTEM_MANDATORY_LABEL_ACE_TYPE: return &static_cast<PSYSTEM_MANDATORY_LABEL_ACE>(pv)->SidStart; case SYSTEM_RESOURCE_ATTRIBUTE_ACE_TYPE: return &static_cast<PSYSTEM_RESOURCE_ATTRIBUTE_ACE>(pv)->SidStart; case SYSTEM_SCOPED_POLICY_ID_ACE_TYPE: return &static_cast<PSYSTEM_SCOPED_POLICY_ID_ACE>(pv)->SidStart; case SYSTEM_PROCESS_TRUST_LABEL_ACE_TYPE: return &static_cast<PSYSTEM_PROCESS_TRUST_LABEL_ACE>(pv)->SidStart; case SYSTEM_ACCESS_FILTER_ACE_TYPE: return &static_cast<PSYSTEM_ACCESS_FILTER_ACE>(pv)->SidStart; default: return nullptr; } } #include <format> #include <iostream> int main() { std::wcout.imbue(std::locale("", std::locale::ctype)); auto windir{GetWindowsDirectoryW()}; auto secutiryDescriptor{::GetFileSecurityW(windir, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION)}; PACL pdacl; BOOL daclPresent; BOOL daclDefaulted; if (!::GetSecurityDescriptorDacl(secutiryDescriptor.data(), &daclPresent, &pdacl, &daclDefaulted)) { return -1; } std::set<std::wstring> names; for (DWORD aceIndex = 0; aceIndex < pdacl->AceCount; aceIndex++) { LPVOID pace; if (!::GetAce(pdacl, aceIndex, &pace)) { return -1; } auto paceHeader{static_cast<PACE_HEADER>(pace)}; auto psidAce{GetAceSid(paceHeader)}; auto aceSidNames{LookupAccountSidW(psidAce)}; names.emplace(aceSidNames.name); } std::wcout << L"Windowsディレクトリのファイルセキュリティグループ名またはユーザー名:" << std::endl; for (std::wstring name : names) { std::wcout << std::format(L" {}", name) << std::endl; } return 0; }