136 lines
3.9 KiB
C++
136 lines
3.9 KiB
C++
#include "util.h"
|
||
|
||
#include <iostream>
|
||
#include <locale>
|
||
#include <codecvt>
|
||
|
||
Uitil::Uitil()
|
||
{
|
||
}
|
||
|
||
std::wstring Uitil::stringToWString(const std::string &string)
|
||
{
|
||
std::wstring_convert<std::codecvt_utf8<wchar_t>> cv;
|
||
|
||
return cv.from_bytes(string);
|
||
}
|
||
|
||
HANDLE Uitil::getCurrentUserToken()
|
||
{
|
||
// 查询sessionID
|
||
PWTS_SESSION_INFO pSessionInfo = 0;
|
||
DWORD dwCount = 0;
|
||
::WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSessionInfo, &dwCount);
|
||
int session_id = 0;
|
||
for (DWORD i = 0; i < dwCount; ++i)
|
||
{
|
||
WTS_SESSION_INFO si = pSessionInfo[i];
|
||
if (WTSActive == si.State)
|
||
{
|
||
session_id = si.SessionId;
|
||
break;
|
||
}
|
||
}
|
||
|
||
::WTSFreeMemory(pSessionInfo);
|
||
|
||
// 查询token
|
||
HANDLE current_token = 0;
|
||
BOOL bRet = ::WTSQueryUserToken(session_id, ¤t_token);
|
||
if (bRet == FALSE)
|
||
{
|
||
std::cout << "WTSQueryUserToken error, code:" << GetLastError() << std::endl;
|
||
|
||
return nullptr;
|
||
}
|
||
|
||
HANDLE primaryToken = 0;
|
||
bRet = ::DuplicateTokenEx(current_token, TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS, 0, SecurityImpersonation, TokenPrimary, &primaryToken);
|
||
::CloseHandle(current_token);
|
||
if (bRet == FALSE)
|
||
{
|
||
std::cout << "DuplicateTokenEx error, code:" << GetLastError() << std::endl;
|
||
|
||
return nullptr;
|
||
}
|
||
|
||
return primaryToken;
|
||
}
|
||
|
||
bool Uitil::runProgAsCurUser(HANDLE token, const std::string &progPath, const std::string &progArgs)
|
||
{
|
||
STARTUPINFO StartupInfo = {0};
|
||
PROCESS_INFORMATION processInfo;
|
||
StartupInfo.cb = sizeof(STARTUPINFO);
|
||
|
||
auto command = std::string("\"") + progPath + "\"";
|
||
if (!progArgs.empty())
|
||
{
|
||
command += " " + progArgs;
|
||
}
|
||
|
||
void* lpEnvironment = NULL;
|
||
BOOL resultEnv = ::CreateEnvironmentBlock(&lpEnvironment, token, FALSE);
|
||
if (!resultEnv)
|
||
{
|
||
std::cout << "CreateEnvironmentBlock error, code:" << GetLastError() << std::endl;
|
||
|
||
return false;
|
||
}
|
||
|
||
std::cout << "runProgAsCurUser, command:" << command << std::endl;
|
||
|
||
// 获取到的hUnfilteredToken就是不受限的token,以token作为CreateProcessAsUser的第一个参数,就可以创建出具有管理员权限,并且属于当前用户的界面程序了,并且这种情况下,不需要加入窗口站。
|
||
BOOL result = ::CreateProcessAsUser(token, 0, (LPSTR)(progPath.c_str()), NULL, NULL, FALSE, CREATE_NEW_CONSOLE | NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT, lpEnvironment, 0, &StartupInfo, &processInfo);
|
||
if(!result)
|
||
{
|
||
std::cout << "CreateProcessAsUser error, code:" << GetLastError() << std::endl;
|
||
|
||
return false;
|
||
}
|
||
|
||
if(lpEnvironment != NULL)
|
||
{
|
||
::DestroyEnvironmentBlock(lpEnvironment);
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
bool Uitil::RunProgAsCurUserAdminPrivilege(const std::string &progPath, const std::string &progArgs)
|
||
{
|
||
// UAC开启时,当前用户拥有两个token,分别是受限的token和不受限的token。explorer.exe进程的token就属于受限的token。
|
||
// 在服务程序中,可以用下面代码获取到受限的token。
|
||
HANDLE primaryToken = getCurrentUserToken();
|
||
if (primaryToken == 0)
|
||
{
|
||
std::cout << "GetCurrentUserToken error." << std::endl;
|
||
|
||
return false;
|
||
}
|
||
|
||
// 由此token可以得到不受限的token
|
||
bool isOpenOk = false;
|
||
HANDLE hUnfilteredToken = NULL;
|
||
DWORD dwSize = 0;
|
||
BOOL bRet = ::GetTokenInformation(primaryToken, TokenLinkedToken, (VOID*)&hUnfilteredToken, sizeof(HANDLE), &dwSize);
|
||
if (bRet)
|
||
{
|
||
isOpenOk = runProgAsCurUser(hUnfilteredToken, progPath, progArgs);
|
||
|
||
::CloseHandle(hUnfilteredToken);
|
||
}
|
||
else
|
||
{
|
||
// UAC未开时,继续使用原来的token打开
|
||
std::cout << "GetTokenInformation error and continue open width primary token. code:" << GetLastError() << std::endl;
|
||
|
||
isOpenOk = runProgAsCurUser(primaryToken, progPath, progArgs);
|
||
}
|
||
|
||
::CloseHandle(primaryToken);
|
||
|
||
return isOpenOk;
|
||
}
|
||
|