c++cwindowswifisid

LookupAccountName Always Fails With Error 122 (ERROR_INSUFFICIENT_BUFFER)


Perhaps somebody can enlighten me here.

I'm attempting to automate a WiFi connection process where the SSID is determined by a serial number. Since this is always different, I figured I need to save a temporary profile each time I wish to connect.

WlanSaveTemporaryProfile() wants a LPCWSTR strAllUserProfileSecurity to define permissions for this profile. So far the rabbit hole has led me to try using LookupAccountNameW(). I have tried to AllocateAndInitializeSid() to no avail. I tried plugging in an empty buffer with the same result. In both cases, I get an error 122, which says the buffer was too small.

Any aid here is sincerely appreciated.


Here's the relevant code. Mostly constructed from examples in Microsoft's documentation.

DWORD GetStringSecurityDescriptor(
    PWCHAR ps_securityDescriptor, /* This needs to be populated when this function completes. */
    PULONG pul_securityDescriptorLen,
    LPWSTR ps_accountName
    )
{
    DWORD dw_result = NULL; 
    DWORD dw_lastError = NULL;
    DWORD dw_bufferSizeOfUserAccount = NULL;

    /* Create a security descriptor for the profile. */
    SECURITY_DESCRIPTOR secDesc;
    bool success = InitializeSecurityDescriptor(&secDesc, SECURITY_DESCRIPTOR_REVISION);
    if (!success)
    {
        wprintf(L"Security Descriptor Initialization Failed.\n");
    }

    PSID p_userSid = NULL;
    /* Attempt 2: Straight up malloc the memory. Doesn't work any better.*/
    //p_userSid = malloc(100);

    /* Attempt 1: Allocate and Initialize an SID for LookupAccountNameW(). */
    SID_IDENTIFIER_AUTHORITY auth = SECURITY_WORLD_SID_AUTHORITY;
    BOOL b_sidReady = AllocateAndInitializeSid(
        &auth,
        6,
        SECURITY_NULL_RID,
        SECURITY_WORLD_RID,
        SECURITY_LOCAL_RID,
        SECURITY_LOCAL_LOGON_RID,
        SECURITY_CREATOR_OWNER_RID,
        SECURITY_CREATOR_GROUP_RID,
        0, 0,
        &p_userSid
        );

    LPDWORD buf = &dw_bufferSizeOfUserAccount;
    WCHAR domainName[1000] = { 0 }; // Perhaps DNLEN + 1 was too small?
    DWORD domainNameLen = 1000;
    SID_NAME_USE use = SidTypeUser;

    // Currently failing. dw_bufferSizeOfUserAccount still recieves a 28, so that wasn't it.
    success = LookupAccountNameW(
        NULL, 
        ps_accountName, 
        p_userSid, 
        buf, 
        domainName, 
        &domainNameLen, 
        &use);
    if (!success) 
    {
        dw_lastError = GetLastError();
        switch (dw_lastError)
        {
        case ERROR_INSUFFICIENT_BUFFER: // LookupAccountNameW() always ends up here.
            wprintf(L"The data area passed to a system call is too small.\n");
            FreeSid(p_userSid);
            return dw_lastError;
        default:
            wprintf(L"Looking up Account Name failed. See Error 0x%x.\n", dw_lastError);
            FreeSid(p_userSid);
            return dw_lastError;
        }
    }

// ... more code irrelevant to this problem...

}

Solution

  • Great thanks to Georgy Firsov!

    I missed a statement in the documentation.

    By calculating the size of the SID and storing it in dw_bufferSizeOfUserAccount, the function ran successfully.

    dw_bufferSizeOfUserAccount = GetLengthSid(p_userSid);