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; }
关键注意点
- 两次调用API:第一次传
NULL作为SID参数,让API返回所需的缓冲区大小;第二次用分配好的内存再调用,才能成功获取账户SID。 - 内存管理:用
LocalAlloc分配内存(符合Windows API的内存管理规范),用完后必须用LocalFree释放,避免内存泄漏。 - 域名缓冲区:虽然你用了1000大小的数组,但用
_countof获取长度更安全,且第二次调用前要重置大小,避免第一次调用后长度被修改导致问题。 - 不要手动构造SID:除非你明确知道目标账户的SID结构,否则不要用
AllocateAndInitializeSid手动创建,而是通过LookupAccountNameW动态获取。
后续安全描述符处理
拿到正确的SID后,你可以继续构建安全描述符:比如用SetSecurityDescriptorOwner设置所有者,再用ConvertSecurityDescriptorToStringSecurityDescriptorW把SECURITY_DESCRIPTOR转换成字符串格式,最终供WlanSaveTemporaryProfile使用。
内容的提问来源于stack exchange,提问作者Googe
相关产品推荐
相关产品推荐

