potisanのプログラミングメモ

趣味のプログラマーがプログラミング関係で気になったことや調べたことをいつでも忘れられるようにメモするブログです。

C++20&Win API&WIL 特権のプライマリドメイン情報(名前・SID)を取得する

#include <string>
#include <iostream>

#define STRICT
#define NOMINMAX
#include <Windows.h>
#include <subauth.h>
#include <ntlsa.h>
#include <sddl.h>

#include <wil/resource.h>

#define THROW_IF_LSA_NTSTATUS_FAILED(status) THROW_IF_NTSTATUS_FAILED(::LsaNtStatusToWinError((status)))

// LSA_UNICODE_STRINGからstd::wstringを作成します。
constexpr std::wstring ToStlWString(const LSA_UNICODE_STRING& source) {
    return std::wstring(source.Buffer, source.Length);
}

// SIDからstd::wstringを作成します。
std::wstring ToStlWString(PSID sid) {
    LPWSTR p;
    if (!::ConvertSidToStringSidW(sid, &p))
        return {};
    std::wstring s(p);
    ::LocalFree(p);
    return std::move(s);
}

int main()
{
    wil::unique_hlsa policyHandle;
    LSA_OBJECT_ATTRIBUTES lsaObjAttrs{ sizeof(LSA_OBJECT_ATTRIBUTES) };
    THROW_IF_LSA_NTSTATUS_FAILED(::LsaOpenPolicy(
        nullptr,
        &lsaObjAttrs,
        POLICY_VIEW_LOCAL_INFORMATION, // LsaQueryInformationPolicy
        policyHandle.put()));

    wil::unique_lsamem_ptr<POLICY_PRIMARY_DOMAIN_INFO> policyPrimaryDomainInfo;
    THROW_IF_LSA_NTSTATUS_FAILED(::LsaQueryInformationPolicy(
        policyHandle.get(),
        PolicyPrimaryDomainInformation,
        wil::out_param_ptr<void**>(policyPrimaryDomainInfo)));

    std::wcout.imbue(std::locale("", std::locale::ctype));
    auto policyPrimaryDomainName{ ToStlWString(policyPrimaryDomainInfo->Name) };
    auto policyPrimaryDomainSid{ ToStlWString(&policyPrimaryDomainInfo->Sid) };
    std::wcout
        << policyPrimaryDomainName << std::endl
        << policyPrimaryDomainSid << std::endl;


    return 0;
}