Run as interactive user from service
The code below runs a program on interactive desktop with logged on user privileges, as it was started by user himself. Must be executed by Local System, for example, by Windows service.
stdafx.h:
#include <WtsApi32.h> #pragma comment(lib, "WtsApi32.lib") #include <Userenv.h> #pragma comment(lib, "Userenv.lib")
RunAsInteractiveUser function:
BOOL bRet; HRESULT hr; HANDLE processToken = NULL; TOKEN_PRIVILEGES oldTokenPrivileges = { 0 }; HANDLE impersonationToken = NULL; HANDLE userToken = NULL; LPVOID pEnvironment = NULL; PROCESS_INFORMATION processInformation = { 0 }; __try { bRet = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &processToken); if (!bRet) { hr = GetLastError(); return hr; } // This step might not be necessary because SeTcbPrivilege is enabled by default for Local System LUID luid; bRet = LookupPrivilegeValue(NULL, _T("SeTcbPrivilege"), &luid); if (!bRet) { hr = GetLastError(); return hr; } TOKEN_PRIVILEGES adjTokenPrivileges = { 0 }; adjTokenPrivileges.PrivilegeCount = 1; adjTokenPrivileges.Privileges[0].Luid = luid; adjTokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; DWORD dwOldTPLen; bRet = AdjustTokenPrivileges(processToken, FALSE, &adjTokenPrivileges, sizeof(TOKEN_PRIVILEGES), &oldTokenPrivileges, &dwOldTPLen); if (bRet) { hr = GetLastError(); if (hr == ERROR_SUCCESS); else if (hr == ERROR_NOT_ALL_ASSIGNED) { // Enabled by default } } else { hr = GetLastError(); return hr; } DWORD conSessId = WTSGetActiveConsoleSessionId(); if (conSessId == 0xFFFFFFFF) { // There is no session attached to the console return ERROR_SUCCESS; } bRet = WTSQueryUserToken(conSessId, &impersonationToken); if (!bRet) { hr = GetLastError(); return hr; } bRet = DuplicateTokenEx(impersonationToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &userToken); if (!bRet) { hr = GetLastError(); return hr; } STARTUPINFO si = { 0 }; si.cb = sizeof(STARTUPINFO); si.lpDesktop = _T("winsta0\\default"); bRet = CreateEnvironmentBlock(&pEnvironment, userToken, TRUE); if (!bRet) { hr = GetLastError(); return hr; } bRet = CreateProcessAsUser(userToken, _T("C:\\Windows\\notepad.exe"), NULL, NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, pEnvironment, NULL, &si, &processInformation); if (!bRet) { hr = GetLastError(); return hr; } } __finally { if (processInformation.hThread) { CloseHandle(processInformation.hThread); } if (processInformation.hProcess) { CloseHandle(processInformation.hProcess); } if (pEnvironment) { bRet = DestroyEnvironmentBlock(pEnvironment); } if (userToken) { CloseHandle(userToken); } if (impersonationToken) { CloseHandle(impersonationToken); } if (processToken) { bRet = AdjustTokenPrivileges(processToken, FALSE, &oldTokenPrivileges, sizeof(TOKEN_PRIVILEGES), NULL, NULL); CloseHandle(processToken); } }