You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LookupAccountNameW调用始终返回ERROR_INSUFFICIENT_BUFFER(122)求助

解决LookupAccountNameW返回ERROR_INSUFFICIENT_BUFFER的问题

我看你在实现WiFi自动连接的临时配置文件时,卡在了LookupAccountNameW返回**ERROR_INSUFFICIENT_BUFFER(错误码122)**的问题上。这个问题的核心是你没遵循Windows API的标准调用流程:LookupAccountNameW需要先获取目标账户SID所需的缓冲区大小,再按需分配内存,而不是提前用固定大小的SID或者随意malloc一块内存。

问题根源分析

你尝试的两种方式都存在逻辑问题:

  • AllocateAndInitializeSid:你创建的是一个固定结构的SID(基于SECURITY_WORLD_SID_AUTHORITY和预设RID),但这并不是目标账户实际对应的SID结构,大小自然不匹配。
  • malloc(100):虽然手动分配了内存,但你不知道目标账户SID实际需要多大空间,盲目分配的内存可能还是不够,而且第一次调用API时也没传NULL来获取正确的大小。

修正后的代码实现

下面是调整后的GetStringSecurityDescriptor函数核心部分,按照正确的API流程处理:

DWORD GetStringSecurityDescriptor( PWCHAR ps_securityDescriptor, 
                                  PULONG pul_securityDescriptorLen, 
                                  LPWSTR ps_accountName ) 
{ 
    DWORD dw_result = NULL; 
    DWORD dw_lastError = NULL; 
    DWORD dw_bufferSizeOfUserAccount = 0; 
    WCHAR domainName[1000] = { 0 }; 
    DWORD domainNameLen = _countof(domainName); // 用_countof获取数组长度更安全
    SID_NAME_USE use = SidTypeUser; 
    PSID p_userSid = NULL;

    // --------------------------
    // 第一步:先调用LookupAccountNameW获取所需的SID缓冲区大小
    // --------------------------
    BOOL success = LookupAccountNameW( NULL, 
                                      ps_accountName, 
                                      NULL, // 传NULL让API返回所需缓冲区大小
                                      &dw_bufferSizeOfUserAccount, 
                                      domainName, 
                                      &domainNameLen, 
                                      &use); 
    if (!success) 
    { 
        dw_lastError = GetLastError(); 
        if (dw_lastError != ERROR_INSUFFICIENT_BUFFER)
        {
            wprintf(L"第一次LookupAccountNameW调用失败,错误码:0x%x.\n", dw_lastError);
            return dw_lastError;
        }
        // 走到这里说明成功获取到了所需的缓冲区大小,接下来分配内存
        p_userSid = LocalAlloc(LPTR, dw_bufferSizeOfUserAccount);
        if (p_userSid == NULL)
        {
            wprintf(L"分配SID内存失败,错误码:0x%x.\n", GetLastError());
            return GetLastError();
        }

        // --------------------------
        // 第二步:用正确的缓冲区再次调用LookupAccountNameW
        // --------------------------
        domainNameLen = _countof(domainName); // 重置域名缓冲区大小
        success = LookupAccountNameW( NULL, 
                                      ps_accountName, 
                                      p_userSid, 
                                      &dw_bufferSizeOfUserAccount, 
                                      domainName, 
                                      &domainNameLen, 
                                      &use); 
        if (!success) 
        { 
            dw_lastError = GetLastError(); 
            wprintf(L"第二次LookupAccountNameW调用失败,错误码:0x%x.\n", dw_lastError);
            LocalFree(p_userSid); // 记得释放内存避免泄漏
            return dw_lastError;
        }
    }

    // 这里继续处理安全描述符的后续逻辑,比如设置所有者、转换为字符串格式等...

    // 用完SID后记得释放内存
    if (p_userSid != NULL)
    {
        LocalFree(p_userSid);
    }

    return ERROR_SUCCESS;
}

关键注意点

  1. 两次调用API:第一次传NULL作为SID参数,让API返回所需的缓冲区大小;第二次用分配好的内存再调用,才能成功获取账户SID。
  2. 内存管理:用LocalAlloc分配内存(符合Windows API的内存管理规范),用完后必须用LocalFree释放,避免内存泄漏。
  3. 域名缓冲区:虽然你用了1000大小的数组,但用_countof获取长度更安全,且第二次调用前要重置大小,避免第一次调用后长度被修改导致问题。
  4. 不要手动构造SID:除非你明确知道目标账户的SID结构,否则不要用AllocateAndInitializeSid手动创建,而是通过LookupAccountNameW动态获取。

后续安全描述符处理

拿到正确的SID后,你可以继续构建安全描述符:比如用SetSecurityDescriptorOwner设置所有者,再用ConvertSecurityDescriptorToStringSecurityDescriptorW把SECURITY_DESCRIPTOR转换成字符串格式,最终供WlanSaveTemporaryProfile使用。

内容的提问来源于stack exchange,提问作者Googe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 08:42:35