S
Sagar R. Kapadia
Guest
I need to launch a process with the credentials of the interactive user. One of the steps in this process requires a call to the API GetTokenInformation. However, if UAC is turned off, this returns error code 1312 on windows 7, and some installations of windows 10. My problem is that I cannot force my users to enable UAC [set it to the highest level]. Is there a way around this issue?
References: GetTokenInformation with TokenLinkedToken returns error 1312 | Remko Weijnen's Blog (Remko's Blog)
The code I use to launch a process with the credentials of the interactive user is as below
STDMETHODIMP CProcessManager::LaunchProcessAsActiveUser(BSTR commandLine, DWORD* dwProcessId)
{
CComBSTR temp(commandLine);
//char * processName = _com_util::ConvertBSTRToString(commandLine);
LPWSTR lpszProcessName = temp.operator LPWSTR(); //CharToWideChar(processName);
Report(L"Process Name: %s", (LPCWSTR)lpszProcessName);
//char *lpszPath = _com_util::ConvertBSTRToString(processName);
DWORD session_id = -1;
DWORD session_count = 0;
WTS_SESSION_INFOA *pSession = NULL;
try {
if (WTSEnumerateSessionsA(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSession, &session_count))
{
//log success
}
else
{
//log error
return S_OK;
}
}
catch (...) {}
Report(L"Session Count :%d", session_count);
Report(L"Begin Enumerating Sesions");
for (int i = 0; i < session_count; i++)
{
/*try*/ {
session_id = pSession.SessionId;
Report(L"SessionId:%d", session_id);
WTS_CONNECTSTATE_CLASS wts_connect_state = WTSDisconnected;
WTS_CONNECTSTATE_CLASS* ptr_wts_connect_state = NULL;
DWORD bytes_returned = 0;
if :WTSQuerySessionInformation(
WTS_CURRENT_SERVER_HANDLE,
session_id,
WTSConnectState,
reinterpret_cast<LPTSTR*>(&ptr_wts_connect_state),
&bytes_returned))
{
wts_connect_state = *ptr_wts_connect_state;
::WTSFreeMemory(ptr_wts_connect_state);
if (wts_connect_state != WTSActive)
{
Report(L"wts_connect_state != WTSActive! Continuing ###");
continue;
}
}
else
{
Report(L"Error in WTSQuerySessionInformation:%d: Continuing ###", GetLastError());
continue;
}
}
//catch (...) {}
Report(L"End Enumerating Sesions");
Report(L"Selected Session Id:%d", session_id);
HANDLE hImpersonationToken;
/*try*/ {
if (!WTSQueryUserToken(session_id, &hImpersonationToken))
{
//log error
Report(L"Exception in WTSQueryUserToken:%d", GetLastError());
continue;
}
}
//catch (...) {}
//Get real token from impersonation token
DWORD neededSize1 = 0;
HANDLE *realToken = new HANDLE;
if (GetTokenInformation(hImpersonationToken, :TOKEN_INFORMATION_CLASS) TokenLinkedToken, realToken, sizeof(HANDLE), &neededSize1))
{
CloseHandle(hImpersonationToken);
hImpersonationToken = *realToken;
}
else
{
//log error
Report(L"Exception in GetTokenInformation:%d", GetLastError());
continue;
}
HANDLE hUserToken;
if (!DuplicateTokenEx(hImpersonationToken,
//0,
//MAXIMUM_ALLOWED,
TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS | MAXIMUM_ALLOWED,
NULL,
SecurityImpersonation,
TokenPrimary,
&hUserToken))
{
//log error
Report(L"Exception in DuplicateTokenEx:%d", GetLastError());
continue;
}
// Get user name of this process
//LPTSTR pUserName = NULL;
WCHAR* pUserName;
DWORD user_name_len = 0;
if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, session_id, WTSUserName, &pUserName, &user_name_len))
{
//log username contained in pUserName WCHAR string
// char * lpszUserName = WideCharToChar(pUserName);
Report(pUserName);
//LocalFree(lpszUserName);
}
else
{
Report(L"Exception in WTSQuerySessionInformation:%d", GetLastError());
return S_OK;
}
//Free memory
if (pUserName) WTSFreeMemory(pUserName);
STARTUPINFOW StartupInfo;
StartupInfo.cb = sizeof(STARTUPINFOW);
GetStartupInfoW(&StartupInfo);
//Uncommented by Sagar 20th January 20118 1612
StartupInfo.lpDesktop = CharToWideChar("winsta0\\default");
//to Hide Console Process 03-10-2018
StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow = SW_HIDE;
LPVOID lpEnvironment = nullptr;
LPWSTR pszPath = nullptr;
if (CreateEnvironmentBlock(&lpEnvironment, hUserToken, FALSE))
{
HRESULT hr;
char cCurrentPath[FILENAME_MAX];
ZeroMemory(cCurrentPath, sizeof(cCurrentPath));
if (TRUE)///*GetCurrentDir(cCurrentPath, sizeof(cCurrentPath))
{
//cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required
Report(L"The current working directory is %s", cCurrentPath);
//pszPath = L"C:\\Users\\Sagar\\Documents\\Visual Studio 2017\\Git Repos\\ConsoleLauncherApp\\Test";
if (ImpersonateLoggedOnUser(hUserToken))
{
STARTUPINFOW si = { sizeof si };
PROCESS_INFORMATION pi = {};
BOOL result = FALSE;
LPWSTR szCmdLine = _tcsdup(lpszProcessName);
Report(szCmdLine);
if (result = CreateProcessAsUserW(hUserToken, nullptr,szCmdLine, nullptr, nullptr, FALSE, NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT, lpEnvironment, /*pszPath*/nullptr, &si, &pi))
{
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
Report(L"CreateProcessAsUser started %s, pid is %d", lpszProcessName, pi.dwProcessId);
*dwProcessId = pi.dwProcessId;
}
else
{
Report(L"CreateProcessAsUser failed with %d", GetLastError());
DWORD err = GetLastError();
Report(L"GetLastError returned: %d", err);
}
}
else
{
Report(L"ImpersonateLoggedOnUser failed with %d\n", GetLastError());
}
RevertToSelf();
Report(L"Created Process:%d", *dwProcessId);
}
DestroyEnvironmentBlock(lpEnvironment);
}
try {
DWORD dwFlags = 0;
if (GetHandleInformation(hImpersonationToken, &dwFlags)) {
CloseHandle(hImpersonationToken);
}
if (GetHandleInformation(hUserToken, &dwFlags)) {
CloseHandle(hUserToken);
}
if (GetHandleInformation(realToken, &dwFlags)) {
CloseHandle(realToken);
}
// RevertToSelf();
}
catch (...) {}
WTSFreeMemory(pSession);
}
return S_OK;
}
Continue reading...
References: GetTokenInformation with TokenLinkedToken returns error 1312 | Remko Weijnen's Blog (Remko's Blog)
The code I use to launch a process with the credentials of the interactive user is as below
STDMETHODIMP CProcessManager::LaunchProcessAsActiveUser(BSTR commandLine, DWORD* dwProcessId)
{
CComBSTR temp(commandLine);
//char * processName = _com_util::ConvertBSTRToString(commandLine);
LPWSTR lpszProcessName = temp.operator LPWSTR(); //CharToWideChar(processName);
Report(L"Process Name: %s", (LPCWSTR)lpszProcessName);
//char *lpszPath = _com_util::ConvertBSTRToString(processName);
DWORD session_id = -1;
DWORD session_count = 0;
WTS_SESSION_INFOA *pSession = NULL;
try {
if (WTSEnumerateSessionsA(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSession, &session_count))
{
//log success
}
else
{
//log error
return S_OK;
}
}
catch (...) {}
Report(L"Session Count :%d", session_count);
Report(L"Begin Enumerating Sesions");
for (int i = 0; i < session_count; i++)
{
/*try*/ {
session_id = pSession.SessionId;
Report(L"SessionId:%d", session_id);
WTS_CONNECTSTATE_CLASS wts_connect_state = WTSDisconnected;
WTS_CONNECTSTATE_CLASS* ptr_wts_connect_state = NULL;
DWORD bytes_returned = 0;
if :WTSQuerySessionInformation(
WTS_CURRENT_SERVER_HANDLE,
session_id,
WTSConnectState,
reinterpret_cast<LPTSTR*>(&ptr_wts_connect_state),
&bytes_returned))
{
wts_connect_state = *ptr_wts_connect_state;
::WTSFreeMemory(ptr_wts_connect_state);
if (wts_connect_state != WTSActive)
{
Report(L"wts_connect_state != WTSActive! Continuing ###");
continue;
}
}
else
{
Report(L"Error in WTSQuerySessionInformation:%d: Continuing ###", GetLastError());
continue;
}
}
//catch (...) {}
Report(L"End Enumerating Sesions");
Report(L"Selected Session Id:%d", session_id);
HANDLE hImpersonationToken;
/*try*/ {
if (!WTSQueryUserToken(session_id, &hImpersonationToken))
{
//log error
Report(L"Exception in WTSQueryUserToken:%d", GetLastError());
continue;
}
}
//catch (...) {}
//Get real token from impersonation token
DWORD neededSize1 = 0;
HANDLE *realToken = new HANDLE;
if (GetTokenInformation(hImpersonationToken, :TOKEN_INFORMATION_CLASS) TokenLinkedToken, realToken, sizeof(HANDLE), &neededSize1))
{
CloseHandle(hImpersonationToken);
hImpersonationToken = *realToken;
}
else
{
//log error
Report(L"Exception in GetTokenInformation:%d", GetLastError());
continue;
}
HANDLE hUserToken;
if (!DuplicateTokenEx(hImpersonationToken,
//0,
//MAXIMUM_ALLOWED,
TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS | MAXIMUM_ALLOWED,
NULL,
SecurityImpersonation,
TokenPrimary,
&hUserToken))
{
//log error
Report(L"Exception in DuplicateTokenEx:%d", GetLastError());
continue;
}
// Get user name of this process
//LPTSTR pUserName = NULL;
WCHAR* pUserName;
DWORD user_name_len = 0;
if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, session_id, WTSUserName, &pUserName, &user_name_len))
{
//log username contained in pUserName WCHAR string
// char * lpszUserName = WideCharToChar(pUserName);
Report(pUserName);
//LocalFree(lpszUserName);
}
else
{
Report(L"Exception in WTSQuerySessionInformation:%d", GetLastError());
return S_OK;
}
//Free memory
if (pUserName) WTSFreeMemory(pUserName);
STARTUPINFOW StartupInfo;
StartupInfo.cb = sizeof(STARTUPINFOW);
GetStartupInfoW(&StartupInfo);
//Uncommented by Sagar 20th January 20118 1612
StartupInfo.lpDesktop = CharToWideChar("winsta0\\default");
//to Hide Console Process 03-10-2018
StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow = SW_HIDE;
LPVOID lpEnvironment = nullptr;
LPWSTR pszPath = nullptr;
if (CreateEnvironmentBlock(&lpEnvironment, hUserToken, FALSE))
{
HRESULT hr;
char cCurrentPath[FILENAME_MAX];
ZeroMemory(cCurrentPath, sizeof(cCurrentPath));
if (TRUE)///*GetCurrentDir(cCurrentPath, sizeof(cCurrentPath))
{
//cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required
Report(L"The current working directory is %s", cCurrentPath);
//pszPath = L"C:\\Users\\Sagar\\Documents\\Visual Studio 2017\\Git Repos\\ConsoleLauncherApp\\Test";
if (ImpersonateLoggedOnUser(hUserToken))
{
STARTUPINFOW si = { sizeof si };
PROCESS_INFORMATION pi = {};
BOOL result = FALSE;
LPWSTR szCmdLine = _tcsdup(lpszProcessName);
Report(szCmdLine);
if (result = CreateProcessAsUserW(hUserToken, nullptr,szCmdLine, nullptr, nullptr, FALSE, NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT, lpEnvironment, /*pszPath*/nullptr, &si, &pi))
{
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
Report(L"CreateProcessAsUser started %s, pid is %d", lpszProcessName, pi.dwProcessId);
*dwProcessId = pi.dwProcessId;
}
else
{
Report(L"CreateProcessAsUser failed with %d", GetLastError());
DWORD err = GetLastError();
Report(L"GetLastError returned: %d", err);
}
}
else
{
Report(L"ImpersonateLoggedOnUser failed with %d\n", GetLastError());
}
RevertToSelf();
Report(L"Created Process:%d", *dwProcessId);
}
DestroyEnvironmentBlock(lpEnvironment);
}
try {
DWORD dwFlags = 0;
if (GetHandleInformation(hImpersonationToken, &dwFlags)) {
CloseHandle(hImpersonationToken);
}
if (GetHandleInformation(hUserToken, &dwFlags)) {
CloseHandle(hUserToken);
}
if (GetHandleInformation(realToken, &dwFlags)) {
CloseHandle(realToken);
}
// RevertToSelf();
}
catch (...) {}
WTSFreeMemory(pSession);
}
return S_OK;
}
Continue reading...