通过SID获取Windows本地组名并添加用户至组的C++技术问题
我来帮你排查代码里的问题,同时解答你关于SID直接添加用户到组的疑问:
问题修复与解决方案
一、修复组名获取的代码问题
你的代码里有几个明显的问题导致组名无法正确输出:
1. 错误的宽字符输出方式
你用cout尝试输出宽字符串(wchar_t类型的buffName),还误用了printf的格式符%ws——cout根本不支持这种格式化语法,而且宽字符应该用wcout来输出:
wcout << L"group name: " << buffName << endl;
原来的cout<<("group name %ws\n", buffName);其实只会输出字符串字面量的内存地址,完全不会正确显示组名。
2. 未释放SID内存
ConvertStringSidToSid返回的PSID是从堆上分配的,必须用LocalFree释放,否则会造成内存泄漏,记得在函数结束前添加释放逻辑。
3. 错误码的正确获取
要在函数失败后立即调用GetLastError(),不然后续的函数调用可能会覆盖错误码,导致你拿到的错误信息不准确。
修复后的完整userNameFromSid函数
std::wstring userNameFromSid() { PSID psid = NULL; BOOL bSucceeded = ConvertStringSidToSid(TEXT("S-1-5-32-544"), &psid); if (!bSucceeded) { wcout << L"Error Converting SID to String, Error code: " << GetLastError() << endl; return L""; } wchar_t buffName[MAX_BUFF_SIZE]; DWORD buffNameSize = MAX_BUFF_SIZE; wchar_t buffDomain[MAX_BUFF_SIZE]; DWORD buffDomainSize = MAX_BUFF_SIZE; SID_NAME_USE SidType = SidTypeGroup; if (LookupAccountSid(NULL, psid, buffName, &buffNameSize, buffDomain, &buffDomainSize, &SidType)) { wcout << L"group name: " << buffName << endl; std::wstring groupName(buffName); LocalFree(psid); // 释放SID内存 return groupName; } else { DWORD errCode = GetLastError(); // 立即获取错误码 wcout << L"LookupAccountSid failed, Error code: " << errCode << endl; LocalFree(psid); return L""; } }
二、能否直接通过SID将用户添加到组?
常用的NetUserAddToGroupAPI确实需要组名作为参数,没办法直接传入SID。不过你可以借助LSA(Local Security Authority)系列API,实现直接通过SID添加用户到组,不需要先转换为组名。
示例代码(通过SID添加用户到组)
下面是一个可运行的示例,使用LSA API完成操作,注意程序需要以管理员权限运行:
#include <windows.h> #include <Sddl.h> #include <LsaLookup.h> #pragma comment(lib, "Advapi32.lib") // 辅助函数:将字符串SID转换为PSID BOOL StringSidToPSID(LPCWSTR sidString, PSID* pSid) { return ConvertStringSidToSid(sidString, pSid); } // 通过SID添加用户到目标组 NTSTATUS AddUserToGroupBySID(LPCWSTR groupSidStr, LPCWSTR userSidStr) { PSID groupSid = NULL; PSID userSid = NULL; LSA_HANDLE policyHandle = NULL; NTSTATUS status = STATUS_UNSUCCESSFUL; // 转换组和用户的字符串SID到PSID结构 if (!StringSidToPSID(groupSidStr, &groupSid) || !StringSidToPSID(userSidStr, &userSid)) { status = STATUS_INVALID_PARAMETER; goto Cleanup; } // 打开本地安全策略 LSA_OBJECT_ATTRIBUTES objAttr; ZeroMemory(&objAttr, sizeof(objAttr)); status = LsaOpenPolicy(NULL, &objAttr, POLICY_ALL_ACCESS, &policyHandle); if (status != STATUS_SUCCESS) { goto Cleanup; } // 将用户SID转换为LSA所需的UNICODE_STRING格式 LSA_UNICODE_STRING userSidLsaStr; if (!ConvertSidToStringSid(userSid, &userSidLsaStr.Buffer)) { status = STATUS_UNSUCCESSFUL; goto Cleanup; } userSidLsaStr.Length = (USHORT)wcslen(userSidLsaStr.Buffer) * sizeof(WCHAR); userSidLsaStr.MaximumLength = userSidLsaStr.Length + sizeof(WCHAR); // 添加用户到组 PLSA_UNICODE_STRING members[] = { &userSidLsaStr }; status = LsaAddMembersToAccount(policyHandle, groupSid, members, 1); Cleanup: // 释放所有分配的资源 if (groupSid) LocalFree(groupSid); if (userSid) LocalFree(userSid); if (policyHandle) LsaClose(policyHandle); if (userSidLsaStr.Buffer) LocalFree(userSidLsaStr.Buffer); return status; } int main() { // 替换为你的用户SID NTSTATUS status = AddUserToGroupBySID(L"S-1-5-32-544", L"S-1-5-21-123456789-1234567890-1234567890-1001"); if (status == STATUS_SUCCESS) { wcout << L"User added to group successfully!" << endl; } else { wcout << L"Failed to add user to group, NTSTATUS code: " << status << endl; } return 0; }
内容的提问来源于stack exchange,提问作者Aria Fathi
相关产品推荐
相关产品推荐

