代码之家  ›  专栏  ›  技术社区  ›  Rob

发现用户是否具有管理权限

  •  2
  • Rob  · 技术社区  · 15 年前

    如何确定当前用户(运行我的应用程序的用户)是否具有管理员权限(即是管理员组的成员)?我需要为访问受限的用户以不同方式注册一些COM组件。我使用的是C++(WTL和Win32)。

    2 回复  |  直到 11 年前
        1
  •  6
  •   Anders    15 年前

    IsUserAnAdmin() 这是一种快速而简单的方法,但msdn警告说,它可能会在将来消失,因此您可能需要打电话给 CheckTokenMembership() 在线程/进程令牌上(与 well known sid 对于管理组)

        2
  •  5
  •   ST3    11 年前

    在工作中,我们使用的是安德斯的建议,但几个月前,由于这个功能,我们的系统失败了。现在我们使用这个:

    bool IsUserAdmin ()
    {
        struct Data
        {
            PACL   pACL;
            PSID   psidAdmin;
            HANDLE hToken;
            HANDLE hImpersonationToken;
            PSECURITY_DESCRIPTOR     psdAdmin;
            Data() : pACL(NULL), psidAdmin(NULL), hToken(NULL),
                hImpersonationToken(NULL), psdAdmin(NULL)
            {}
            ~Data()
            {
                if (pACL) 
                    LocalFree(pACL);
                if (psdAdmin) 
                    LocalFree(psdAdmin);
                if (psidAdmin) 
                    FreeSid(psidAdmin);
                if (hImpersonationToken) 
                    CloseHandle (hImpersonationToken);
                if (hToken) 
                    CloseHandle (hToken);
            }
        } data;
    
    BOOL   fReturn         = FALSE;
    Dword  dwStatus;
    Dword  dwAccessMask;
    Dword  dwAccessDesired;
    Dword  dwACLSize;
    Dword  dwStructureSize = sizeof(PRIVILEGE_SET);
    
    PRIVILEGE_SET   ps;
    GENERIC_MAPPING GenericMapping;
    SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY;
    
    const DWORD ACCESS_READ  = 1;
    const DWORD ACCESS_WRITE = 2;
    
    if (!OpenThreadToken (GetCurrentThread(), TOKEN_DUPLICATE|TOKEN_QUERY, TRUE, &data.hToken))
    {
        if (GetLastError() != ERROR_NO_TOKEN)
            return false;
    
        if (!OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE|TOKEN_QUERY, &data.hToken))
            return false;
    }
    
    if (!DuplicateToken (data.hToken, SecurityImpersonation, &data.hImpersonationToken))
        return false;
    
    if (!AllocateAndInitializeSid(&SystemSidAuthority, 2,
                                SECURITY_BUILTIN_DOMAIN_RID,
                                DOMAIN_ALIAS_RID_ADMINS,
                                0, 0, 0, 0, 0, 0, &data.psidAdmin))
        return false;
    
    data.psdAdmin = LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
    if (data.psdAdmin == NULL)
        return false;
    
    if (!InitializeSecurityDescriptor(data.psdAdmin, SECURITY_DESCRIPTOR_REVISION))
        return false;
    
    // Compute size needed for the ACL.
    dwACLSize = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(data.psidAdmin) - sizeof(DWORD);
    
    data.pACL = (PACL)LocalAlloc(LPTR, dwACLSize);
    if (data.pACL == NULL)
        return false;
    
    if (!InitializeAcl(data.pACL, dwACLSize, ACL_REVISION2))
        return false;
    
    dwAccessMask = ACCESS_READ | ACCESS_WRITE;
    
    if (!AddAccessAllowedAce(data.pACL, ACL_REVISION2, dwAccessMask, data.psidAdmin))
        return false;
    
    if (!SetSecurityDescriptorDacl(data.psdAdmin, TRUE, data.pACL, FALSE))
        return false;
    
    // AccessCheck validates a security descriptor somewhat; set the group
    // and owner so that enough of the security descriptor is filled out 
    // to make AccessCheck happy.
    
    SetSecurityDescriptorGroup(data.psdAdmin, data.psidAdmin, FALSE);
    SetSecurityDescriptorOwner(data.psdAdmin, data.psidAdmin, FALSE);
    
    if (!IsValidSecurityDescriptor(data.psdAdmin))
        return false;
    
    dwAccessDesired = ACCESS_READ;
    
    GenericMapping.GenericRead    = ACCESS_READ;
    GenericMapping.GenericWrite   = ACCESS_WRITE;
    GenericMapping.GenericExecute = 0;
    GenericMapping.GenericAll     = ACCESS_READ | ACCESS_WRITE;
    
    if (!AccessCheck(data.psdAdmin, data.hImpersonationToken, dwAccessDesired,
                    &GenericMapping, &ps, &dwStructureSize, &dwStatus,
                    &fReturn))
    {
        return false;
    }
    
    return fReturn;
    }