ファイルのプロパティ、セキュリティタブのグループ名またはユーザー名に表示される名前をACE毎に取得するコードです。セキュリティ記述子とDACLの学習用でもあります。
コード
#include <array> #include <string> #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); } constexpr std::wstring_view SID_NAME_USEToStringW(SID_NAME_USE use) noexcept { auto names = std::array{ L"SidTypeUser", L"SidTypeGroup", L"SidTypeDomain", L"SidTypeAlias", L"SidTypeWellKnownGroup", L"SidTypeDeletedAccount", L"SidTypeInvalid", L"SidTypeUnknown", L"SidTypeComputer", L"SidTypeLabel", L"SidTypeLogonSession"}; auto i = static_cast<int>(use - 1); if (0 <= i && i < names.size()) return names[i]; else return {}; } constexpr std::wstring_view AceTypeToStringW(BYTE aceType) noexcept { auto names = std::array{ L"ACCESS_ALLOWED_ACE_TYPE", L"ACCESS_DENIED_ACE_TYPE", L"SYSTEM_AUDIT_ACE_TYPE", L"SYSTEM_ALARM_ACE_TYPE", L"ACCESS_ALLOWED_COMPOUND_ACE_TYPE", L"ACCESS_ALLOWED_OBJECT_ACE_TYPE", L"ACCESS_DENIED_OBJECT_ACE_TYPE", L"SYSTEM_AUDIT_OBJECT_ACE_TYPE", L"SYSTEM_ALARM_OBJECT_ACE_TYPE", L"ACCESS_ALLOWED_CALLBACK_ACE_TYPE", L"ACCESS_DENIED_CALLBACK_ACE_TYPE", L"ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE", L"ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE", L"SYSTEM_AUDIT_CALLBACK_ACE_TYPE", L"SYSTEM_ALARM_CALLBACK_ACE_TYPE", L"SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE", L"SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE", L"SYSTEM_MANDATORY_LABEL_ACE_TYPE", L"SYSTEM_RESOURCE_ATTRIBUTE_ACE_TYPE", L"SYSTEM_SCOPED_POLICY_ID_ACE_TYPE", L"SYSTEM_PROCESS_TRUST_LABEL_ACE_TYPE", L"SYSTEM_ACCESS_FILTER_ACE_TYPE" }; if (0 <= aceType && aceType < names.size()) return names[aceType]; else return {}; } 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)}; PSID ownerSid; BOOL ownerDefaulted; if (!GetSecurityDescriptorOwner( secutiryDescriptor.data(), &ownerSid, &ownerDefaulted)) { return -1; } auto ownerSidNames{LookupAccountSidW(ownerSid)}; std::wcout << std::format(L"オーナーSID: {} {} ({})\n", ownerSidNames.name, ownerSidNames.referenceDomainName, SID_NAME_USEToStringW(ownerSidNames.use)); PACL pdacl; BOOL daclPresent; BOOL daclDefaulted; if (!::GetSecurityDescriptorDacl(secutiryDescriptor.data(), &daclPresent, &pdacl, &daclDefaulted)) { return -1; } 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)}; std::wcout << std::format(L"ACE{} ({})\n SID: {} {} ({})\n", aceIndex, AceTypeToStringW(paceHeader->AceType), aceSidNames.name, aceSidNames.referenceDomainName, SID_NAME_USEToStringW(aceSidNames.use)); } return 0; }