I have a C# Application, which is launched from a C++ DLL using CreateProcessAsUserW api. The process is launched successfully, but terminates immediately. It works properly on Windows 10 [both as 32 bit and 64 bit] and 32 bit on Windows 7.
Please help.
Thanks,
Sagar
The method is as follows
STDMETHODIMP CProcessManager::LaunchProcessAsActiveUser(BSTR processName, LONG* dwProcessId)
{
wchar_t* path = (wchar_t*)processName;
DWORD session_id = -1;
DWORD session_count = 0;
WTS_SESSION_INFOA *pSession = NULL;
if (WTSEnumerateSessionsA(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSession, &session_count))
{
}
else
{
return S_OK;
}
logger->Log(L"Session Count", session_count);
logger->Log(L"Begin Enumerating Sesions");
for (int i = 0; i < session_count; i++)
{
session_id = pSession[i].SessionId;
logger->Log(L"SessionId", 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) continue;
}
else
{
continue;
}
logger->Log(L"End Enumerating Sesions");
logger->Log(L"Selected Session Id", session_id);
HANDLE hImpersonationToken;
if (!WTSQueryUserToken(session_id, &hImpersonationToken))
{
logger->Log(L"Exception in WTSQueryUserToken", GetLastError());
continue;
}
DWORD neededSize1 = 0;
HANDLE *realToken = new HANDLE;
if (GetTokenInformation(hImpersonationToken, (::TOKEN_INFORMATION_CLASS) TokenLinkedToken, realToken, sizeof(HANDLE), &neededSize1))
{
CloseHandle(hImpersonationToken);
hImpersonationToken = *realToken;
}
else
{
logger->Log(L"Exception in GetTokenInformation", GetLastError());
continue;
}
HANDLE hUserToken;
if (!DuplicateTokenEx(hImpersonationToken,
TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS | MAXIMUM_ALLOWED,
NULL,
SecurityImpersonation,
TokenPrimary,
&hUserToken))
{
logger->Log(L"Exception in DuplicateTokenEx", GetLastError());
continue;
}
WCHAR* pUserName;
DWORD user_name_len = 0;
if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, session_id, WTSUserName, &pUserName, &user_name_len))
{
logger->Log(pUserName);
}
else
{
logger->Log(L"Exception in WTSQuerySessionInformation", GetLastError());
}
if (pUserName) WTSFreeMemory(pUserName);
ImpersonateLoggedOnUser(hUserToken);
STARTUPINFOW StartupInfo;
StartupInfo.cb = sizeof(STARTUPINFOW);
ZeroMemory(&StartupInfo, sizeof(StartupInfo));
StartupInfo.lpDesktop = CharToWideChar("winsta0\\default");
StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow = SW_SHOW;
PROCESS_INFORMATION processInfo;
SECURITY_ATTRIBUTES Security1;
ZeroMemory(&Security1, sizeof(Security1));
Security1.nLength = sizeof SECURITY_ATTRIBUTES;
SECURITY_ATTRIBUTES Security2;
ZeroMemory(&Security2, sizeof(Security2));
Security2.nLength = sizeof SECURITY_ATTRIBUTES;
void* lpEnvironment = NULL;
BOOL resultEnv = CreateEnvironmentBlock(&lpEnvironment, hUserToken, FALSE);
if (!resultEnv)
{
DWORD err = GetLastError();
logger->Log(L"Exception in CreateEnvironmentBlock", err);
continue;
}
WCHAR PP[1024];
ZeroMemory(PP, 1024 * sizeof WCHAR);
wcscpy_s(PP, path);
wcscat_s(PP, L" ");
BOOL result = CreateProcessAsUserW(hUserToken,
PP,
NULL,
&Security1,
&Security2,
FALSE,
NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,
NULL,
NULL,
&StartupInfo,
&processInfo);
if (!result)
{
logger->Log(L"Failed to create process", PP);
DWORD err = GetLastError();
logger->Log(L"GetLastError returned", err);
}
else
{
*dwProcessId = processInfo.dwProcessId;
logger->Log(L"Created Process", *dwProcessId);
}
DestroyEnvironmentBlock(lpEnvironment);
CloseHandle(hImpersonationToken);
CloseHandle(hUserToken);
CloseHandle(realToken);
RevertToSelf();
}
WTSFreeMemory(pSession);
return S_OK;
}
What I have tried:
I found the following link,
https://stackoverflow.com/questions/15581142/why-is-this-process-crashing-as-soon-as-it-is-launched
however, process monitor from SysInternals finds no missing dll. [I can attach the saved logs from ProcMon] I also tried passing the path to the application folder, as suggested elsewhere, in the lpCurrentDirectory parameter of the API, but that did not work either.
I followed the guidance in /https://stackoverflow.com/questions/14315013/how-to-get-the-active-user-when-multiple-users-are-logged-on-in-windows to write the code which launches the process,
and the method which launches the process is called from a windows service.To emulate that from the command line, I used the following
https://stackoverflow.com/questions/77528/how-do-you-run-cmd-exe-under-the-local-system-account [psexec64 -i -s cmd.exe, and then launched the process from cmd.exe]