//启动应用程序,path:程序的路径,带exe的,dir:程序的工作路径
BOOL LaunchApplication(LPTSTR path, LPTSTR dir)
{
char buf[128] = { 0 };
BOOL bRet = FALSE;
HANDLE hUserTokenDup = NULL;
LPVOID pEnv = NULL;
do
{
DWORD dwSessionId = 0;
if (0xFFFFFFFF == (dwSessionId = WTSGetActiveConsoleSessionId())) {
Logger::getInstance()->info(__FILE__, __LINE__, "WTSGetActiveConsoleSessionId fail");
break;
}
#define DEFAULT_WINLOGON_APPLICATION (TEXT("winlogon.exe"))
#define DEFAULT_DEFAULT_APPLICATION (TEXT("explorer.exe")) // 需要以explorer.exe进程的Token来创建Env环境块,否则以服务启动的App在打开文件路径的方面可能会遇到一些问题,比如最常见的是会访问C:\Windows\System32\config\systemprofile导致访问了错误的位置。
DWORD dwWinlogonPid = 0;
if (0xFFFFFFFF == (dwWinlogonPid = GetProcessID(DEFAULT_WINLOGON_APPLICATION, dwSessionId)))
{
Logger::getInstance()->info(__FILE__, __LINE__, "Get Process ID Failed!");
break;
}
if (NULL == (hUserTokenDup = GetProcessTokenDup(dwWinlogonPid)))
{
Logger::getInstance()->info(__FILE__, __LINE__, "Get Process Duplicate Token Failed!");
break;
}
if (!AdjustProcessTokenDup(hUserTokenDup, dwSessionId)) {
Logger::getInstance()->info(__FILE__, __LINE__, "Adjust Process Token Failed!");
break;
}
sprintf_s(buf, "dwSessionId=%d", dwSessionId);
Logger::getInstance()->info(__FILE__, __LINE__, "Adjust Process Token Failed!");
//HANDLE hDefaultTokenDup2 = NULL;
//DWORD dwDefaultPid = 0;
//if (0xFFFFFFFF == (dwDefaultPid = GetProcessID(DEFAULT_DEFAULT_APPLICATION, dwSessionId))) {
// /*PRINT(ERR, TEXT("Get Process ID Failed!"));*/
// break;
//}
//if (NULL == (hDefaultTokenDup2 = GetProcessTokenDup(dwDefaultPid))) {
// /*PRINT(ERR, TEXT("Get Process Duplicate Token Failed!")); */
// break;
//}
// Create Environment Block
/*DWORD dwCreateFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
if (CreateEnvironmentBlock(&pEnv, hDefaultTokenDup2, TRUE)) { dwCreateFlags |= CREATE_UNICODE_ENVIRONMENT; }*/
// Launch Process In The Client's Logon Session
/*TCHAR szExecute[MAX_PATH] = { 0 };
GetModuleFileName(NULL, szExecute, _countof(szExecute));
_tcsrchr(szExecute, TEXT('\\'))[1] = TEXT('\0');
StringCbCat(szExecute, _countof(szExecute) - _tcslen(szExecute), lpszExecute);*/
/*TCHAR szCmdLine[MAX_PATH] = { 0 };
if (NULL != lpszCmdLine) {
StringCchPrintf(szCmdLine, _countof(szCmdLine), TEXT("%s"), lpszCmdLine);
}*/
PROCESS_INFORMATION pi = { 0 };
SECURITY_ATTRIBUTES sa = {0};
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
STARTUPINFO si = { sizeof(STARTUPINFO) };
si.lpDesktop = TEXT("winsta0\\default");
si.wShowWindow = SW_SHOW;
si.dwFlags = STARTF_USESHOWWINDOW;
si.cb = sizeof(STARTUPINFO);
BOOL ret = CreateProcessAsUser(hUserTokenDup,
path,
NULL,
&sa,
&sa,
FALSE,
NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT,
NULL,
dir,
&si,
&pi);
if (!ret)
{
sprintf_s(buf, "ret=%d,nError=%d", ret, GetLastError());
Logger::getInstance()->info(__FILE__, __LINE__, buf);
break;
}
char buf[128] = { 0 };
sprintf_s(buf, "CreateProcessAsUser :ret=%d,nError=%d", ret, GetLastError());
Logger::getInstance()->info(__FILE__, __LINE__, buf);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
// Completed
bRet = TRUE;
} while (FALSE);
if (NULL != pEnv) { DestroyEnvironmentBlock(pEnv); pEnv = NULL; }
if (NULL != hUserTokenDup) { CloseHandle(hUserTokenDup); hUserTokenDup = NULL; }
return bRet;
}
DWORD GetProcessID(LPCTSTR lpszProcessName, DWORD dwSessionId)
{
DWORD dwProcessId = 0xFFFFFFFF;
HANDLE hSnapshot = INVALID_HANDLE_VALUE;
do
{
_ASSERT(NULL != lpszProcessName);
if (NULL == lpszProcessName) { break; }
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (INVALID_HANDLE_VALUE == hSnapshot) {
Logger::getInstance()->info(__FILE__, __LINE__, "CreateToolhelp32Snapshot error");
break;
}
PROCESSENTRY32 pe32 = { sizeof(PROCESSENTRY32) };
if (!Process32First(hSnapshot, &pe32)) {
Logger::getInstance()->info(__FILE__, __LINE__, "Process32First error");
break;
}
do
{
if (0 == _tcsicmp(pe32.szExeFile, lpszProcessName))
{
DWORD dwProcessSessionId = 0;
if (ProcessIdToSessionId(pe32.th32ProcessID, &dwProcessSessionId)
&& (dwSessionId == dwProcessSessionId))
{
dwProcessId = pe32.th32ProcessID;
break;
}
}
} while (Process32Next(hSnapshot, &pe32));
// Completed
} while (FALSE);
if (INVALID_HANDLE_VALUE != hSnapshot) { CloseHandle(hSnapshot); hSnapshot = INVALID_HANDLE_VALUE; }
return dwProcessId;
}
HANDLE GetProcessTokenDup(DWORD dwProcessId)
{
HANDLE hProcess = NULL;
HANDLE hToken = NULL;
HANDLE hTokenDup = NULL;
do
{
if (NULL == (hProcess = OpenProcess(MAXIMUM_ALLOWED, FALSE, dwProcessId))) {
Logger::getInstance()->info(__FILE__, __LINE__, "OpenProcess");//PRINT(ERR, GetLastError(), TEXT("OpenProcess"));
break;
}
if (!OpenProcessToken(hProcess,
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_SESSIONID | TOKEN_READ | TOKEN_WRITE,
&hToken))
{
Logger::getInstance()->info(__FILE__, __LINE__, "OpenProcessToken");
break;
}
if (!DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &hTokenDup)) {
Logger::getInstance()->info(__FILE__, __LINE__, "DuplicateTokenEx");
break;
}
// Completed
} while (FALSE);
if (NULL != hToken) { CloseHandle(hToken); hToken = NULL; }
if (NULL != hProcess) { CloseHandle(hProcess); hProcess = NULL; }
return hTokenDup;
}
BOOL AdjustProcessTokenDup(HANDLE hTokenDup, DWORD dwSessionId)
{
BOOL bRet = FALSE;
do
{
if (NULL == hTokenDup) { break; }
// Adjust Token Privileges
if (!SetTokenInformation(hTokenDup, TokenSessionId, (LPVOID)&dwSessionId, sizeof(dwSessionId))) {
Logger::getInstance()->info(__FILE__, __LINE__, "SetTokenInformation");
break;
}
if (!AdjustTokenDupPrivileges(hTokenDup, SE_DEBUG_NAME)) { Logger::getInstance()->info(__FILE__, __LINE__, "Enable SE_DEBUG_NAME Privilege Failed!"); }
if (!AdjustTokenDupPrivileges(hTokenDup, SE_TCB_NAME)) { Logger::getInstance()->info(__FILE__, __LINE__, "Enable SE_TCB_NAME Privilege Failed!");}
if (!AdjustTokenDupPrivileges(hTokenDup, SE_CHANGE_NOTIFY_NAME)) { Logger::getInstance()->info(__FILE__, __LINE__, "Enable SE_CHANGE_NOTIFY_NAME Privilege Failed!");}
if (!AdjustTokenDupPrivileges(hTokenDup, SE_INCREASE_QUOTA_NAME)) { Logger::getInstance()->info(__FILE__, __LINE__, "Enable SE_INCREASE_QUOTA_NAME Privilege Failed!"); }
if (!AdjustTokenDupPrivileges(hTokenDup, SE_ASSIGNPRIMARYTOKEN_NAME)) { Logger::getInstance()->info(__FILE__, __LINE__, "Enable SE_ASSIGNPRIMARYTOKEN_NAME Privilege Failed!"); }
// Completed
bRet = TRUE;
} while (FALSE);
return bRet;
}
BOOL AdjustTokenDupPrivileges(HANDLE hTokenDup, LPCTSTR lpszPrivileges)
{
BOOL bRet = FALSE;
do
{
LUID luid = { 0 };
if (!LookupPrivilegeValue(NULL, lpszPrivileges, &luid))
{
Logger::getInstance()->info(__FILE__, __LINE__, "LookupPrivilegeValue");//PRINT(ERR, GetLastError(), TEXT("LookupPrivilegeValue"));
break;
}
TOKEN_PRIVILEGES tp = { 0 };
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// Adjust token privileges
if (!AdjustTokenPrivileges(hTokenDup, FALSE, &tp, sizeof(tp), NULL, NULL))
{
Logger::getInstance()->info(__FILE__, __LINE__, "AdjustTokenPrivileges");//PRINT(ERR, GetLastError(), TEXT("AdjustTokenPrivileges"));
break;
}
// Completed
bRet = TRUE;
} while (FALSE);
return bRet;
}