在Windows服务进程中启动需管理员权限(带盾牌图标)的应用程序

//启动应用程序,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:WindowsSystem32configsystemprofile导致访问了错误的位置。

		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('');
		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;
}

  

原文地址:https://www.cnblogs.com/alinh/p/12410526.html