登录系统以后,在Windows服务进程中启动需管理员权限(带盾牌图标)的应用程序

// 创建交互式服务安装完成以后,启动UI的程序
BOOL LaunchApplication(LPCTSTR lpszExecute, LPCTSTR lpszCmdLine)
{
	BOOL bRet = FALSE;
	HANDLE hUserTokenDup = NULL;
	LPVOID pEnv = NULL;
	do
	{
		DWORD dwSessionId = 0;
		if (0xFFFFFFFF == (dwSessionId = WTSGetActiveConsoleSessionId())) { PRINT(ERR, GetLastError(), TEXT("WTSGetActiveConsoleSessionId")); 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))) { PRINT(ERR, TEXT("Get Process ID Failed!")); break; }
		if (NULL == (hUserTokenDup = GetProcessTokenDup(dwWinlogonPid))) { PRINT(ERR, TEXT("Get Process Duplicate Token Failed!")); break; }
		if (!AdjustProcessTokenDup(hUserTokenDup, dwSessionId)) { PRINT(ERR, TEXT("Adjust Process Token Failed!")); break; }

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

		#define DEFAULT_DESKTOP_WINSTA0				(TEXT("winsta0\\default"))

		PROCESS_INFORMATION pi = { 0 };
		STARTUPINFO si = { sizeof(STARTUPINFO) };
		si.lpDesktop = DEFAULT_DESKTOP_WINSTA0;

		if (!CreateProcessAsUser(hUserTokenDup,
			szExecute,
			szCmdLine,
			NULL,
			NULL,
			FALSE,
			dwCreateFlags,
			pEnv,
			NULL,
			&si,
			&pi)) 
		{
			PRINT(ERR, GetLastError(), TEXT("CreateProcessAsUser"));
			break;
		}
		
		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) { PRINT(ERR, GetLastError(), TEXT("CreateToolhelp32Snapshot")); break; }

		PROCESSENTRY32 pe32 = { sizeof(PROCESSENTRY32) };
		if (!Process32First(hSnapshot, &pe32)) { PRINT(ERR, GetLastError(), TEXT("Process32First")); 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))) { 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))
		{
			PRINT(ERR, GetLastError(), TEXT("OpenProcessToken"));
			break;
		}

		if (!DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &hTokenDup)) { PRINT(ERR, GetLastError(), TEXT("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))) { PRINT(ERR, GetLastError(), TEXT("SetTokenInformation")); break; }

		if (!AdjustTokenDupPrivileges(hTokenDup, SE_DEBUG_NAME)) { PRINT(ERR, TEXT("Enable SE_DEBUG_NAME Privilege Failed!")); }
		if (!AdjustTokenDupPrivileges(hTokenDup, SE_TCB_NAME)) { PRINT(ERR, TEXT("Enable SE_TCB_NAME Privilege Failed!")); }
		if (!AdjustTokenDupPrivileges(hTokenDup, SE_CHANGE_NOTIFY_NAME)) { PRINT(ERR, TEXT("Enable SE_CHANGE_NOTIFY_NAME Privilege Failed!")); }
		if (!AdjustTokenDupPrivileges(hTokenDup, SE_INCREASE_QUOTA_NAME)) { PRINT(ERR, TEXT("Enable SE_INCREASE_QUOTA_NAME Privilege Failed!")); }
		if (!AdjustTokenDupPrivileges(hTokenDup, SE_ASSIGNPRIMARYTOKEN_NAME)) { PRINT(ERR, TEXT("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))
		{
			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))
		{
			PRINT(ERR, GetLastError(), TEXT("AdjustTokenPrivileges"));
			break;
		}
		// Completed
		bRet = TRUE;
	} while (FALSE);
	return bRet;
}

void PRINT(DWORD dwLevel, LPCTSTR lpszFormat, ...)
{
	do
	{
		if (!m_bDbgValid) { break; }

		TCHAR szText[DEFAULT_PRINTF_BUFFER_LENGTH] = { 0 };
		TCHAR szBuffer[DEFAULT_PRINTF_BUFFER_LENGTH] = { 0 };

		// Parse Parameter
		va_list args;
		va_start(args, lpszFormat);
		StringCchVPrintf(szBuffer, _countof(szBuffer), lpszFormat, args);
		va_end(args);

		// Format
		FORMAT(szText, _countof(szText), szBuffer);

		// Dump
		DUMP(dwLevel, szText);
	} while (FALSE);
}

void PRINT(DWORD dwLevel, DWORD dwErrorId, LPCTSTR lpszDescription)
{
	do
	{
		if (!m_bDbgValid) { break; }

		TCHAR szText[DEFAULT_PRINTF_BUFFER_LENGTH] = { 0 };

		// Format
		FORMAT(szText, _countof(szText), dwErrorId, lpszDescription);

		// Dump
		DUMP(dwLevel, szText);
	} while (FALSE);
}

void CCommon::FORMAT(LPTSTR lpszText, size_t nLength, LPCTSTR lpszInfo)
{
	_ASSERT(NULL != lpszText);
	_ASSERT(nLength > 0);
	_ASSERT(NULL != lpszInfo);

	SYSTEMTIME st = { 0 };
	GetLocalTime(&st);

	StringCchPrintf(lpszText, 
		nLength, 
		TEXT("[%04d-%02d-%02d %02d:%02d:%02d.%03d] - %s\r\n"),
		st.wYear,
		st.wMonth,
		st.wDay,
		st.wHour,
		st.wMinute,
		st.wSecond,
		st.wMilliseconds,
		lpszInfo);
}

void FORMAT(LPTSTR lpszText, size_t nLength, DWORD dwErrorId, LPCTSTR lpszDescription)
{
	_ASSERT(NULL != lpszText);
	_ASSERT(nLength > 0);
	_ASSERT(NULL != lpszDescription);

	SYSTEMTIME st = { 0 };
	GetLocalTime(&st);
	
	TCHAR szBuffer[DEFAULT_PRINTF_BUFFER_LENGTH] = { 0 };
	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwErrorId, LANG_NEUTRAL, (LPTSTR)szBuffer, _countof(szBuffer), NULL);
	StringCchPrintf(lpszText,
		nLength,
		TEXT("[%04d-%02d-%02d %02d:%02d:%02d.%03d] - Call %s() Failed with Error: %d - %s\r\n"),
		st.wYear,
		st.wMonth,
		st.wDay,
		st.wHour,
		st.wMinute,
		st.wSecond,
		st.wMilliseconds,
		lpszDescription,
		dwErrorId,
		szBuffer);

}


猜你喜欢

转载自blog.csdn.net/visualeleven/article/details/80247383
今日推荐