スレッドまたはプロセスのトークンのユーザー情報SIDから文字列表記・ユーザー名・参照ドメイン名を取得するコードです。Win32 API関数のラッパー関数・クラスを定義していますが、サンプルコードなので名前空間で囲ったりはしていません。
#include <bit> #include <vector> #include <string> #include <memory> #define STRICT #define NOMINMAX #include <Windows.h> #include <sddl.h> struct HANDLEDeleter final { inline void operator() (HANDLE Handle) const noexcept { ::CloseHandle(Handle); } }; using unique_handle = std::unique_ptr<std::remove_pointer_t<HANDLE>, HANDLEDeleter>; BOOL OpenCurrentThreadOrProcessToken(DWORD DesiredAccess, BOOL ThreadOpenAsSelf, unique_handle& Result) noexcept; BOOL GetTokenInformation(HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, std::vector<BYTE>& Result) noexcept; BOOL ConvertSidToStringSidW(PSID Sid, std::wstring& Result) noexcept; BOOL LookupAccountSidW(LPCWSTR SystemName, PSID Sid, std::wstring& Name, std::wstring& ReferencedDomainName, SID_NAME_USE& Use); // トークンのユーザー情報を管理します。 // GetTokenInformation関数を使用します。 class TokenUserInformation final { public: constexpr TokenUserInformation(HANDLE tokenHandle) { std::vector<BYTE> buffer; if (!::GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS::TokenUser, buffer)) return {}; m_buffer = std::move(buffer); } constexpr TokenUserInformation(TokenUserInformation&& source) : m_buffer(std::move(source.m_buffer)) { } constexpr TokenUserInformation(const TokenUserInformation& source) = delete; constexpr bool IsEmpty() const noexcept { return m_buffer.empty(); } constexpr void Swap(TokenUserInformation& x) noexcept { m_buffer.swap(x.m_buffer); } constexpr void Clear() noexcept { m_buffer.clear(); } constexpr explicit operator const TOKEN_USER* () const noexcept { return std::bit_cast<const TOKEN_USER*>(m_buffer.data()); } constexpr const TOKEN_USER* operator->() const noexcept { return std::bit_cast<const TOKEN_USER*>(m_buffer.data()); } private: std::vector<BYTE> m_buffer; }; int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int) { // スレッドまたはプロセスのトークンを取得します。 unique_handle tokenHandle; if (!OpenCurrentThreadOrProcessToken(TOKEN_QUERY, TRUE, tokenHandle)) return GetLastError(); // トークンからユーザートークンのSIDを取得します。 TokenUserInformation userInfo(tokenHandle.get()); // SIDの情報を取得します。 std::wstring strSid; // SIDの文字列表記 std::wstring userName; // ユーザー名 std::wstring referencedDomainName; // 参照ドメイン名 SID_NAME_USE sidNameUse; // ユーザー名の用法 ConvertSidToStringSidW(userInfo->User.Sid, strSid); LookupAccountSidW(nullptr, userInfo->User.Sid, userName, referencedDomainName, sidNameUse); return 0; } // 現在のスレッドまたはプロセスのトークンを取得します。 BOOL OpenCurrentThreadOrProcessToken(DWORD DesiredAccess, BOOL ThreadOpenAsSelf, unique_handle& Result) noexcept { HANDLE TokenHandle{ nullptr }; if (!OpenThreadToken(GetCurrentThread(), DesiredAccess, ThreadOpenAsSelf, &TokenHandle)) { if (GetLastError() != ERROR_NO_TOKEN) return FALSE; if (!OpenProcessToken(GetCurrentProcess(), DesiredAccess, &TokenHandle)) return FALSE; } Result.reset(TokenHandle); return TRUE; } // トークン情報を取得します。 BOOL GetTokenInformation(HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, std::vector<BYTE>& Result) noexcept { DWORD size{ 0 }; if (!GetTokenInformation(TokenHandle, TokenInformationClass, nullptr, 0, &size)) { if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return FALSE; } Result.resize(size); return GetTokenInformation(TokenHandle, TokenInformationClass, Result.data(), size, &size); } // Win32 API ConvertSidToStringSidW関数のSTLラッパーです。 BOOL ConvertSidToStringSidW(PSID Sid, std::wstring& Result) noexcept { LPWSTR ps; if (!ConvertSidToStringSidW(Sid, &ps)) return FALSE; std::wstring s(ps, wcslen(ps)); LocalFree(ps); Result = std::move(s); return TRUE; } // Win32 API LookupAccountSidW関数のSTLラッパーです。 BOOL LookupAccountSidW(LPCWSTR SystemName, PSID Sid, std::wstring& Name, std::wstring& ReferencedDomainName, SID_NAME_USE& Use) { DWORD nameSize{ 0 }; DWORD refDomainNameSize{ 0 }; SID_NAME_USE sidNameUse; LookupAccountSidW( SystemName, Sid, nullptr, &nameSize, nullptr, &refDomainNameSize, &sidNameUse); Name.resize(nameSize); ReferencedDomainName.resize(refDomainNameSize); return LookupAccountSidW( nullptr, Sid, &*Name.begin(), &nameSize, &*ReferencedDomainName.begin(), &refDomainNameSize, &Use); }