Alexandru Antochi
Alexandru Antochi

Reputation: 1465

LookupAccountName error when ReferencedDomainName is NULL

If I do not save the optional ReferencedDomainName in a variable, the function returns false and I can no retrieve the used Sid. If the doc says it's optional, why do I need to include that as well? Here is my code:

This works and returns a 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;

But If I remove the DomainName and change the size=0 as per MSDN Documentation, I get a 122 error and no Sid is returned;

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

Upvotes: 2

Views: 3368

Answers (2)

Anders
Anders

Reputation: 101746

I can't tell you why they force you to retrieve the domain when you just want the Sid but that is the way the API is designed and there is nothing you can do about it. The domain parameter is optional because the API is designed to be called twice, once to retrieve the required buffer sizes and once to actually fill the buffers.

If you don't like this design you can abstract it away with a helper function:

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.");
}

Upvotes: 5

user7860670
user7860670

Reputation: 37600

If you supply null instead of DomainName function will store required DomainName buffer size in size and last error will be ERROR_INSUFFICIENT_BUFFER (122). So to get actual results you must supply DomainName buffer of sufficient capacity.

Upvotes: 2

Related Questions