如何确定是否在本地管理员帐户的用户上下文中运行线程

注意:这篇文章是由无人工介入的微软自动的机器翻译软件翻译完成。微软很高兴能同时提供给您由人工翻译的和由机器翻译的文章, 以使您能使用您的语言访问所有的知识库文章。然而由机器翻译的文章并不总是完美的。它可能存在词汇,语法或文法的问题,就像是一个外国人在说中文时总是可能犯这样的错误。虽然我们经常升级机器翻译软件以提高翻译质量,但是我们不保证机器翻译的正确度,也不对由于内容的误译或者客户对它的错误使用所引起的任何直接的, 或间接的可能的问题负责。

点击这里察看该文章的英文版: 118626
概要
要确定是否在本地管理员帐户下运行的线程,您必须检查与线程相关联的访问令牌。本文介绍如何执行此操作。

Windows 2000 及更高版本中,您可以使用 CheckTokenMembership() API 而不是本文所述步骤。有关更多的信息,请参阅 Microsoft 平台 SDK 文档。
更多信息
默认状态下,与线程相关联的标记是进程的其包含。此"用户上下文"任何直接连接到该线程的标识被取代。因此,以确定线程的用户上下文,您应首先尝试获得具有 OpenThreadToken 函数线程令牌。如果此方法将失败并 GetLastError 函数报告 ERROR_NO_TOKEN,然后您可以获取为具有 OpenProcessToken 函数的进程令牌。

获取当前用户的令牌后,您可以使用 AccessCheck 函数来检测用户是否是管理员。若要这样做,请按照下列步骤操作:
  1. 通过使用 AllocateAndInitializeSid 函数中创建本地管理员组的安全的标识符 (SID)。
  2. 构造一个新的安全描述符 (SD) 与一个自由访问控制列表 (DACL) 包含访问控制项 (ACE) 的管理员组的 SID。
  3. 调用 AccessCheck 与当前用户和新构造的结构化数据来检测用户是否是管理员的标记。
下面的代码示例使用测试当前线程正在运行的用户身份是在本地计算机上的管理员是否本文中前面提到的函数。

示例代码

#include <windows.h>#include <stdio.h>#include <lmcons.h>BOOL IsCurrentUserLocalAdministrator(void);void main(int argc, char **argv){   if (IsCurrentUserLocalAdministrator())      printf("You are an administrator\n");   else      printf("You are not an administrator\n");}/*--------------------------------------------------------------------------IsCurrentUserLocalAdministrator ()This function checks the token of the calling thread to see if the callerbelongs to the Administrators group.Return Value:   TRUE if the caller is an administrator on the local machine.   Otherwise, FALSE.--------------------------------------------------------------------------*/BOOL IsCurrentUserLocalAdministrator(void){   BOOL   fReturn         = FALSE;   DWORD  dwStatus;   DWORD  dwAccessMask;   DWORD  dwAccessDesired;   DWORD  dwACLSize;   DWORD  dwStructureSize = sizeof(PRIVILEGE_SET);   PACL   pACL            = NULL;   PSID   psidAdmin       = NULL;   HANDLE hToken              = NULL;   HANDLE hImpersonationToken = NULL;   PRIVILEGE_SET   ps;   GENERIC_MAPPING GenericMapping;   PSECURITY_DESCRIPTOR     psdAdmin           = NULL;   SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY;   /*      Determine if the current thread is running as a user that is a member of      the local admins group.  To do this, create a security descriptor that      has a DACL which has an ACE that allows only local aministrators access.      Then, call AccessCheck with the current thread's token and the security      descriptor.  It will say whether the user could access an object if it      had that security descriptor.  Note: you do not need to actually create      the object.  Just checking access against the security descriptor alone      will be sufficient.   */   const DWORD ACCESS_READ  = 1;   const DWORD ACCESS_WRITE = 2;   __try   {      /*         AccessCheck() requires an impersonation token.  We first get a primary         token and then create a duplicate impersonation token.  The         impersonation token is not actually assigned to the thread, but is         used in the call to AccessCheck.  Thus, this function itself never         impersonates, but does use the identity of the thread.  If the thread         was impersonating already, this function uses that impersonation context.      */      if (!OpenThreadToken(GetCurrentThread(), TOKEN_DUPLICATE|TOKEN_QUERY, TRUE, &hToken))      {         if (GetLastError() != ERROR_NO_TOKEN)            __leave;         if (!OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE|TOKEN_QUERY, &hToken))            __leave;      }      if (!DuplicateToken (hToken, SecurityImpersonation, &hImpersonationToken))          __leave;      /*        Create the binary representation of the well-known SID that        represents the local administrators group.  Then create the security        descriptor and DACL with an ACE that allows only local admins access.        After that, perform the access check.  This will determine whether        the current user is a local admin.      */      if (!AllocateAndInitializeSid(&SystemSidAuthority, 2,                                    SECURITY_BUILTIN_DOMAIN_RID,                                    DOMAIN_ALIAS_RID_ADMINS,                                    0, 0, 0, 0, 0, 0, &psidAdmin))         __leave;      psdAdmin = LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);      if (psdAdmin == NULL)         __leave;      if (!InitializeSecurityDescriptor(psdAdmin, SECURITY_DESCRIPTOR_REVISION))         __leave;      // Compute size needed for the ACL.      dwACLSize = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) +                  GetLengthSid(psidAdmin) - sizeof(DWORD);      pACL = (PACL)LocalAlloc(LPTR, dwACLSize);      if (pACL == NULL)         __leave;      if (!InitializeAcl(pACL, dwACLSize, ACL_REVISION2))         __leave;      dwAccessMask= ACCESS_READ | ACCESS_WRITE;      if (!AddAccessAllowedAce(pACL, ACL_REVISION2, dwAccessMask, psidAdmin))         __leave;      if (!SetSecurityDescriptorDacl(psdAdmin, TRUE, pACL, FALSE))         __leave;      /*         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(psdAdmin, psidAdmin, FALSE);      SetSecurityDescriptorOwner(psdAdmin, psidAdmin, FALSE);      if (!IsValidSecurityDescriptor(psdAdmin))         __leave;      dwAccessDesired = ACCESS_READ;      /*         Initialize GenericMapping structure even though you         do not use generic rights.      */      GenericMapping.GenericRead    = ACCESS_READ;      GenericMapping.GenericWrite   = ACCESS_WRITE;      GenericMapping.GenericExecute = 0;      GenericMapping.GenericAll     = ACCESS_READ | ACCESS_WRITE;      if (!AccessCheck(psdAdmin, hImpersonationToken, dwAccessDesired,                       &GenericMapping, &ps, &dwStructureSize, &dwStatus,                       &fReturn))      {         fReturn = FALSE;         __leave;      }   }   __finally   {      // Clean up.      if (pACL) LocalFree(pACL);      if (psdAdmin) LocalFree(psdAdmin);      if (psidAdmin) FreeSid(psidAdmin);      if (hImpersonationToken) CloseHandle (hImpersonationToken);      if (hToken) CloseHandle (hToken);   }   return fReturn;}

警告:本文已自动翻译

属性

文章 ID:118626 - 上次审阅时间:11/21/2006 15:29:45 - 修订版本: 4.3

Microsoft Win32 Application Programming Interface

  • kbmt kbapi kbhowto kbkernbase kbsecurity KB118626 KbMtzh
反馈