调用CreateWellKnownSid指定WinAccountAdministratorSid报错,如何获取本地DomainSid?
问题原因与解决方案
你遇到的“参数不正确”错误,核心原因是WinAccountAdministratorSid这个SID类型的特殊性,和你成功使用的WinBuiltinAdministratorsSid/WinBuiltinUsersSid完全不同:
WinBuiltinAdministratorsSid是通用的内置管理员组SID,它不依赖具体的域或本地机器,所以调用CreateWellKnownSid时可以直接传NULL作为DomainSid参数。WinAccountAdministratorSid是绑定到特定域/本地机器的内置管理员用户SID,它是基于域/机器的基础SID生成的,必须指定对应的DomainSid参数(不能传NULL),否则就会触发参数错误。
如何获取本地计算机的DomainSid?
要获取本地机器的SID(也就是本地环境下的DomainSid),可以通过LookupAccountNameW函数实现——把本地机器名作为查询对象,就能拿到机器对应的SID。
修改后的完整代码示例
#include <Windows.h> #include <wchar.h> #include <LM.h> #include <locale.h> #pragma comment(lib, "Netapi32.lib") #define MAX_NAME 256 VOID ShowError(DWORD errorCode) { DWORD flags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS; LPWSTR errorMessage; DWORD size = 0; if (!FormatMessageW(flags, NULL, errorCode, 0, (LPWSTR)&errorMessage, size, NULL)) { fwprintf(stderr, L"Could not get the format message, error code: %u\n", GetLastError()); exit(1); } wprintf(L"\n%s", errorMessage); LocalFree(errorMessage); } int wmain(int argc, WCHAR **argv) { _wsetlocale(LC_ALL, L"English"); // 第一步:获取本地计算机的SID(DomainSid) WCHAR computerName[MAX_COMPUTERNAME_LENGTH + 1]; DWORD computerNameLen = MAX_COMPUTERNAME_LENGTH + 1; if (!GetComputerNameW(computerName, &computerNameLen)) { ShowError(GetLastError()); return 1; } PSID domainSid = NULL; DWORD domainSidSize = 0; WCHAR domainName[MAX_NAME]; DWORD domainNameSize = MAX_NAME; SID_NAME_USE sidType; // 第一次调用LookupAccountNameW,获取所需内存的大小 LookupAccountNameW(NULL, computerName, NULL, &domainSidSize, domainName, &domainNameSize, &sidType); if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { ShowError(GetLastError()); return 1; } // 分配内存存储DomainSid domainSid = (PSID)LocalAlloc(LMEM_FIXED, domainSidSize); if (!domainSid) { ShowError(GetLastError()); return 1; } // 第二次调用,真正获取本地机器的SID if (!LookupAccountNameW(NULL, computerName, domainSid, &domainSidSize, domainName, &domainNameSize, &sidType)) { ShowError(GetLastError()); LocalFree(domainSid); return 1; } // 第二步:获取内置管理员用户的SID UINT memFlags = LMEM_FIXED; DWORD numOfBytes = SECURITY_MAX_SID_SIZE; PSID builtInAdminSid = (PSID)LocalAlloc(memFlags, numOfBytes); if (!builtInAdminSid) { ShowError(GetLastError()); LocalFree(domainSid); return 1; } WELL_KNOWN_SID_TYPE accountAdminSid = WinAccountAdministratorSid; if (!CreateWellKnownSid(accountAdminSid, domainSid, builtInAdminSid, &numOfBytes)) { ShowError(GetLastError()); LocalFree(builtInAdminSid); LocalFree(domainSid); return 1; } // 这里可以添加对builtInAdminSid的使用逻辑,比如转换为字符串输出等 // 记得释放所有分配的内存 LocalFree(builtInAdminSid); LocalFree(domainSid); return 0; }
关键细节说明
- 获取本地机器SID:先用
GetComputerNameW拿到本地机器的NetBIOS名称,再通过LookupAccountNameW查询这个名称对应的SID——因为本地机器本身也是一个安全主体,它的SID就是我们需要的DomainSid。 - CreateWellKnownSid的正确调用:现在传入获取到的
domainSid作为第二个参数,就能成功生成绑定到本地机器的内置管理员用户SID了。 - 内存管理:所有通过
LocalAlloc分配的内存,一定要在使用完成后用LocalFree释放,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Sergio Calderon
相关产品推荐
相关产品推荐

