C++ ReferenceDomainName为NULL时发生LookupAccountName错误

C++ ReferenceDomainName为NULL时发生LookupAccountName错误,c++,windows,winapi,msdn,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 = (LPST

如果我没有在变量中保存可选的
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;
但是如果我删除
DomainName
并根据MSDN文档更改
size=0
,我会得到一个122错误,并且不会返回任何
Sid

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

如果您提供null而不是
DomainName
,函数将在
size
中存储所需的
DomainName
缓冲区大小,最后一个错误是
error\u buffer
(122)。因此,要获得实际结果,您必须提供足够容量的
DomainName
缓冲区。

我无法告诉您,当您只需要Sid时,为什么他们会强制您检索域,但API就是这样设计的,您对此无能为力。domain参数是可选的,因为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.");
}

但我不想这样,我只想要Sid,文档上说域名是可选的。如果我必须提供它,它似乎不是可选的。@AlexandruAntochi“可选”表示允许为空。然而,这并不意味着在这种情况下,函数将执行相同的工作。它只报告所需的缓冲区大小,仅此而已。@AlexandruAntochi:您不必提供域名。这是一个
Out
参数。您只需提供一个缓冲区即可接收它。顺便说一句,SID仅在与域结合时才有意义。你是否想要这个域名并不重要。SID是特定于域的。