当 ReferencedDomainName 为 NULL 时 LookupAccountName 错误

Ale*_*chi 2 c++ windows winapi msdn

如果我不将可选值保存ReferencedDomainName在变量中,函数将返回false,并且我无法检索使用的 Sid。如果文档说它是可选的,为什么我还需要包含它?这是我的代码:

这有效并返回一个 SID:

    DWORD size;
    TCHAR lpAccountName[USERNAME_SIZE];
    PSID Sid = (PSID)LocalAlloc(LPTR, SECURITY_MAX_SID_SIZE);
    LPSTR DomainName = (LPSTR)LocalAlloc(LPTR, sizeof(TCHAR) * 1024);
    DWORD cbSid = SECURITY_MAX_SID_SIZE;
    LPSTR userSIDBuffer = (LPSTR)LocalAlloc(LPTR, sizeof(TCHAR) * cbSid);
    SID_NAME_USE peUse;

    size = USERNAME_SIZE;
    if (!GetUserName(lpAccountName, &size))
    {
        _error("Could not retrieve username.");
    }

    printf("Username found: %s\n", lpAccountName);

    size = 1024;
    if (!LookupAccountName(NULL, lpAccountName, Sid, &cbSid, DomainName, &size, &peUse))
    {
        _error("Could not look up account.");
    }

    return Sid;
Run Code Online (Sandbox Code Playgroud)

但是如果我按照 MSDN 文档删除DomainName并更改,我会收到 122 错误并且不会返回任何内容;size=0Sid

        size = 0;
        if (!LookupAccountName(NULL, lpAccountName, Sid, &cbSid, NULL, &size, &peUse))
        {
            _error("Could not look up account.");
        }
Run Code Online (Sandbox Code Playgroud)

And*_*ers 5

我无法告诉你为什么当你只想要 Sid 时他们强迫你检索域,但这就是 API 的设计方式,你对此无能为力。域参数是可选的,因为 API 被设计为调用两次,一次用于检索所需的缓冲区大小,一次用于实际填充缓冲区。

如果您不喜欢这种设计,您可以使用辅助函数将其抽象化:

BOOL GetAccountSidFromName(LPCTSTR Account, PSID Sid, const DWORD SidSize)
{
    SID_NAME_USE snu;
    DWORD cbSid = SidSize, cchRD = 0;
    LPTSTR rd = NULL;
    BOOL succ = LookupAccountName(NULL, Account, Sid, &cbSid, rd, &cchRD, &snu);
    if (!succ)
    {
        if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
            return FALSE;
        rd = (LPTSTR) LocalAlloc(LPTR, cchRD * sizeof(*rd));
        if (!rd)
        {
            SetLastError(ERROR_OUTOFMEMORY);
            return FALSE;
        }
        cbSid = SidSize;
        succ = LookupAccountName(NULL, Account, Sid, &cbSid, rd, &cchRD, &snu);
        LocalFree(rd);
    }
    return succ;
}

...

TCHAR lpAccountName[USERNAME_SIZE];
DWORD size = USERNAME_SIZE;
if (!GetUserName(lpAccountName, &size))
{
    _error("Could not retrieve username.");
}
BYTE sidbuf[SECURITY_MAX_SID_SIZE];
PSID sid = (PSID) sidbuf;
BOOL success = GetAccountSidFromName(lpAccountName, sid, sizeof(sidbuf));
if (!success)
{
    _error("Could not retrieve sid.");
}
Run Code Online (Sandbox Code Playgroud)