#include <iostream>
#include <windows.h>
#include <tchar.h>
#include <shlobj.h>
using namespace std;
//查看进程是否具有管理员权限
//可以把这个函数当API来用
//这个函数返回一个bool值,当函数返回true,函数成功
/*
* 参数说明:
* TOKEN_ELEVATION_TYPE *pElevationType:获得当前令牌的等级,确认令牌提升类型
* TOKEN_ELEVATION_TYPE 是一个枚举类型enum
*
* 第一个TokenElevationTypeDefaule:进程以缺省的用户身份运行,或者没有使用UAC功能,简单来说,就是用户没有启动UAC功能,那么程序使用的令牌,一定不是FilterToken
* 第二个TokenElevationTypeFull:进程的权限已被提升,进程令牌没有使用filtertoken
* 第三个TokenElevationTypeLimited:进程使用的令牌是Filter令牌,此时通过GetTokenInformaiton函数,并使用TokenLinkedToken标志,来获取原令牌(管理员令牌)
*
* BOOL* pIsAdmin:是否是管理员
*
* 程序步骤:
* 1.先通过GetTokenInfomation函数来确定,当前进程的令牌是否为FilterToken
* 2.如果是,那么通过GetTokenInformation函数,来获取FilterToken的原始令牌
* 3.在获得原始令牌后,通过CheckTokenMembership函数,确认在原始令牌中,是否有管理员的账号,
* 如果有,说明启动当前程序的账户是管理员账户,否则就不是
* CheckTokenMembership确认一个SID是否在一个Token中可用。
* 4.如果不是FilterToken,那么直接使用IsUserAnAdmin函数,来确定启动当前程序的账号,是否为管理员
*/
BOOL GetProcessElevation(TOKEN_ELEVATION_TYPE* pElevationType, BOOL* pIsAdmin)
{
HANDLE hToken = NULL;
DWORD dwSize;
//获得当前进程的令牌句柄
// TOKEN_QUERY 查询权限
if(!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
{
return FALSE;
}
BOOL bResult = FALSE;
//查看令牌的权限提升类型是哪一种?
/*
* 缺省
* 已被提升
* 未被提升
*/
//GetTokenInformation能获得很多种令牌信息,我们只查看是否为上三种
if(GetTokenInformation(hToken,
TokenElevationType,
pElevationType,
sizeof (TOKEN_ELEVATION_TYPE),
&dwSize))
{
//创建一个管理员SID
BYTE adminSID[SECURITY_MAX_SID_SIZE];
dwSize = sizeof(adminSID);
CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, &adminSID, &dwSize);
//如果拿到的是一个FilerToken
if(*pElevationType == TokenElevationTypeLimited)
{
//通过FilterToken来获得原始的Token
HANDLE hunfilteredToken = NULL;
//TokenLinkedToken标志,表示要获得FilterToken的原始token
GetTokenInformation(hToken,
TokenLinkedToken,
(VOID*)&hunfilteredToken,
sizeof (HANDLE),
&dwSize);
//检查原始token中,管理员账户adminSID是否被激活,如果被激活,那么说明启动这个程序的账号是管理员账号
if(CheckTokenMembership(hunfilteredToken, &adminSID, pIsAdmin))
{
//CheckTokenMembership函数的结果保存在pIsAdmin参数中,而这个函数的返回值只是说明函数是否成功
bResult = TRUE;
}
//关闭句柄
CloseHandle(hunfilteredToken);
}
else
{
//如果是原始令牌,只要IsUserAndmin就可以确定当前程序的账号是否为管理员账号
*pIsAdmin = IsUserAnAdmin();
bResult = TRUE;
}
}
//关闭进程令牌
CloseHandle(hToken);
return bResult;
}
int main()
{
TOKEN_ELEVATION_TYPE Type;
BOOL IsAdmin;
BOOL re = GetProcessElevation(&Type,&IsAdmin);
if(re)
{
wcout << Type << endl;
if(IsAdmin)
{
wcout << "on Admin running!" << endl;
}
else
{
wcout << "on normal acount running!" << endl;
}
}
getchar();
return 0;
}