Example #1
30
// create the child process with command line "-runas session -parent [parent process id]"
// the child process will run in the specified session
HANDLE CWinRobotService::CreateChildProcess(ULONG sid)
{
	TrackDebugOut;

	WCHAR szComd[MAX_PATH*2];
	WCHAR curpath[MAX_PATH];
	GetModuleFileNameW( 0, curpath, MAX_PATH );
	PathRemoveFileSpec(curpath);
	DWORD dwProcessId = 0;
	HANDLE hNewToken = NULL;
	HRESULT hr = S_OK;
	HWINSTA  hwinsta = NULL;
	HANDLE hToken= NULL;
	void* pEnvBlock = NULL;
	PROCESS_INFORMATION pi;
	ZeroMemory(&pi,sizeof(pi));
	DWORD errcode=0;

	try
	{
		DebugOutF(filelog::log_info,"attempt to CreateChildProcess %d",sid);
// 		HANDLE hCurProcess = 0;
// 
// 		DuplicateHandle(GetCurrentProcess(),GetCurrentProcess(), GetCurrentProcess(), &hCurProcess, 
// 			0, TRUE, DUPLICATE_SAME_ACCESS);
#ifdef _WIN64
		swprintf(szComd,L"\"%s\\WinRobotHostx64.exe\" -runas session -parent %d",curpath,GetProcessId(GetCurrentProcess()));
#else
		swprintf(szComd,L"\"%s\\WinRobotHostx86.exe\" -runas session -parent %d",curpath,GetProcessId(GetCurrentProcess()));
#endif
		STARTUPINFOW si;
		ZeroMemory(&si, sizeof(STARTUPINFOW));
		si.cb= sizeof(STARTUPINFOW);

		DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS;

		si.lpDesktop = L"winsta0\\default";;

		INT  *pState = NULL;
		DWORD buflen = 0;
		ConnectActiveSession();

		if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ALL_ACCESS,&hToken)){
			DebugOutF(filelog::log_error,"OpenProcessToken failed , error code = %d",GetLastError());
			throw E_UNEXPECTED;
		}
		// Duplicate the token because we need modify it
		if(!DuplicateTokenEx(hToken,MAXIMUM_ALLOWED,0,SecurityAnonymous ,TokenPrimary ,&hNewToken)){
			errcode = GetLastError();
			DebugOutF(filelog::log_error,"DuplicateTokenEx failed , error code = %d",GetLastError());
			throw HRESULT_FROM_WIN32(errcode);
		}
		// change the token so that the process will be create in the new session
		if(!SetTokenInformation(hNewToken,TokenSessionId,&sid,sizeof(DWORD)))
		{
			errcode = GetLastError();
			DebugOutF(filelog::log_error,"SetTokenInformation failed , error code = %d",GetLastError());
			throw HRESULT_FROM_WIN32(errcode);
		}
 		if(!CreateEnvironmentBlock( &pEnvBlock, hToken, TRUE)){
 			DebugOutF(filelog::log_error,"CreateEnvironmentBlock Failed, error code = %d",GetLastError());
 		}else{
 			dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
 		}
		BOOL bCreate = FALSE;
		for(int i=0;i<5;i++)
		{
			if(!(bCreate = CreateProcessAsUserW(hNewToken,
				0,szComd,0,0,FALSE,dwCreationFlags ,pEnvBlock,curpath,&si,&pi )))
			{
				if(GetLastError() == 233){
					// change the token so that the process will be create in the new session
					sid = 0;
					if(!SetTokenInformation(hNewToken,TokenSessionId,&sid,sizeof(DWORD)))
					{
						errcode = GetLastError();
						DebugOutF(filelog::log_error,"SetTokenInformation failed , error code = %d",GetLastError());
						throw HRESULT_FROM_WIN32(errcode);
					}
					continue;
				}
				Sleep(300);
				continue;
			}
			else
			{
				break;
			}
		}
		if(bCreate)
		{
			DebugOutF(filelog::log_info,"CreateChildProcess on session %d ok",sid);
		}
		else
		{
			DebugOutF(filelog::log_error,"CreateProcessAsUser on session %d %s,%s,failed error code = %d"
				,sid,(char*)CW2A(szComd),(char*)CW2A(curpath),GetLastError());
		}
	}
	catch (HRESULT hr1)
	{
		hr = hr1;
	}

	if(hToken) CloseHandle(hToken);
	if(hNewToken)CloseHandle(hNewToken);
	if(pi.hThread){CloseHandle(pi.hThread);pi.hThread = 0;}
	if(pEnvBlock)DestroyEnvironmentBlock(pEnvBlock);
	return pi.hProcess;
}
Example #2
0
static BOOL
StartTaskManager(
    IN OUT PWLSESSION Session)
{
    LPVOID lpEnvironment;
    BOOL ret;

    if (!Session->Gina.Functions.WlxStartApplication)
        return FALSE;

    if (!CreateEnvironmentBlock(
        &lpEnvironment,
        Session->UserToken,
        TRUE))
    {
        return FALSE;
    }

    ret = Session->Gina.Functions.WlxStartApplication(
        Session->Gina.Context,
        L"Default",
        lpEnvironment,
        L"taskmgr.exe");

    DestroyEnvironmentBlock(lpEnvironment);
    return ret;
}
Example #3
0
static BOOL
StartUserShell(
    IN OUT PWLSESSION Session)
{
    LPVOID lpEnvironment = NULL;
    BOOLEAN Old;
    BOOL ret;

    /* Create environment block for the user */
    if (!CreateEnvironmentBlock(&lpEnvironment, Session->UserToken, TRUE))
    {
        WARN("WL: CreateEnvironmentBlock() failed\n");
        return FALSE;
    }

    /* Get privilege */
    /* FIXME: who should do it? winlogon or gina? */
    /* FIXME: reverting to lower privileges after creating user shell? */
    RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, TRUE, FALSE, &Old);

    ret = Session->Gina.Functions.WlxActivateUserShell(
                Session->Gina.Context,
                L"Default",
                NULL, /* FIXME */
                lpEnvironment);

    DestroyEnvironmentBlock(lpEnvironment);
    return ret;
}
Example #4
0
int main(int argc, char *argv[])
{
    static const WCHAR svcctl_started_event[] = SVCCTL_STARTED_EVENT;
    DWORD err;

    g_hStartedEvent = CreateEventW(NULL, TRUE, FALSE, svcctl_started_event);
    load_registry_parameters();
    err = scmdatabase_create(&active_database);
    if (err != ERROR_SUCCESS)
        return err;
    if ((err = scmdatabase_load_services(active_database)) != ERROR_SUCCESS)
        return err;
    if ((err = RPC_Init()) == ERROR_SUCCESS)
    {
        scmdatabase_autostart_services(active_database);
        events_loop();
        scmdatabase_wait_terminate(active_database);
    }
    scmdatabase_destroy(active_database);
    if (env)
        DestroyEnvironmentBlock(env);

    WINE_TRACE("services.exe exited with code %d\n", err);
    return err;
}
Example #5
0
int OOBase::Environment::get_user(HANDLE hToken, env_table_t& tabEnv)
{
	LPVOID lpEnv = NULL;
	if (!CreateEnvironmentBlock(&lpEnv,hToken,FALSE))
		return GetLastError();

	int err = process_block(static_cast<wchar_t*>(lpEnv),tabEnv);
		
	if (lpEnv)
		DestroyEnvironmentBlock(lpEnv);

	return err;
}
Example #6
0
BOOL
WINAPI
ExpandEnvironmentStringsForUserW(IN HANDLE hToken,
                                 IN LPCWSTR lpSrc,
                                 OUT LPWSTR lpDest,
                                 IN DWORD dwSize)
{
    BOOL Ret = FALSE;
    PVOID lpEnvironment;

    if (lpSrc == NULL || lpDest == NULL || dwSize == 0)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }

    if (CreateEnvironmentBlock(&lpEnvironment,
                               hToken,
                               FALSE))
    {
        UNICODE_STRING SrcU, DestU;
        NTSTATUS Status;

        /* Initialize the strings */
        RtlInitUnicodeString(&SrcU, lpSrc);
        DestU.Length = 0;
        DestU.MaximumLength = dwSize * sizeof(WCHAR);
        DestU.Buffer = lpDest;

        /* Expand the strings */
        Status = RtlExpandEnvironmentStrings_U((PWSTR)lpEnvironment,
                                               &SrcU,
                                               &DestU,
                                               NULL);

        DestroyEnvironmentBlock(lpEnvironment);

        if (NT_SUCCESS(Status))
        {
            Ret = TRUE;
        }
        else
        {
            SetLastError(RtlNtStatusToDosError(Status));
        }
    }

    return Ret;
}
Example #7
0
void wmain(int argc, WCHAR *argv[])
{
    DWORD     dwSize;
    HANDLE    hToken;
    LPVOID    lpvEnv;
    PROCESS_INFORMATION pi = {0};
    STARTUPINFO         si = {0};
    WCHAR               szUserProfile[256] = L"";

    si.cb = sizeof(STARTUPINFO);

    if (argc != 4)
    {
        /*    wprintf(L"Usage: %s [user@domain] [password] [cmd]", argv[0]);
            wprintf(L"\n\n"); */
        //   return;
    }

    dwSize = sizeof(szUserProfile)/sizeof(WCHAR);


    OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,&hToken);
    //ShowLastError(L"OpenProcessToken");
    //SetPrivilege(&hToken, SE_SYSTEMTIME_NAME,TRUE);
    // if(!SetPrivilege(hToken, SE_TCB_NAME , TRUE)) printf("Set Privilege Failed");// DisplayError(L"SetPrivilege");
    //if (!LogonUser(argv[1], NULL , argv[2], LOGON32_LOGON_INTERACTIVE,    LOGON32_PROVIDER_DEFAULT, &hToken))       DisplayError(L"LogonUser");

    if (!CreateEnvironmentBlock(&lpvEnv, hToken, TRUE))    ShowLastError(L"CreateEnvironmentBlock");

    dwSize = sizeof(szUserProfile)/sizeof(WCHAR);

    if (!GetUserProfileDirectory(hToken, szUserProfile, &dwSize))        ShowLastError(L"GetUserProfileDirectory");
    //
    // TO DO: change NULL to '.' to use local account database
    //
    if (!CreateProcessWithLogonW(argv[1], NULL, argv[2],             LOGON_WITH_PROFILE, NULL, argv[3],             CREATE_UNICODE_ENVIRONMENT, lpvEnv, szUserProfile,             &si, &pi))

        ShowLastError(L"CreateProcessWithLogonW");

    if (!DestroyEnvironmentBlock(lpvEnv))        ShowLastError(L"DestroyEnvironmentBlock");


    CloseHandle(hToken);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
}
Example #8
0
runner::env_vars_list_t runner::set_environment_for_process() const
{
    auto curr_vars = read_environment(GetEnvironmentStringsW());

    if (options.environmentMode == "user-default")
    {
        LPVOID envBlock = NULL;

        CreateEnvironmentBlock(&envBlock, NULL, FALSE);

        auto default_vars = read_environment((WCHAR*)envBlock);

        DestroyEnvironmentBlock(envBlock);

        for (auto i = default_vars.cbegin(); i != default_vars.cend(); ++i)
        {
            SetEnvironmentVariableA(i->first.c_str(), i->second.c_str());
        }

        for (auto i = curr_vars.cbegin(); i != curr_vars.cend(); ++i)
        {
            if (std::find(default_vars.cbegin(), default_vars.cend(), *i) == default_vars.cend())
            {
                SetEnvironmentVariableA(i->first.c_str(), NULL);
            }
        }
    }
    else if (options.environmentMode == "clear")
    {
        for (auto i = curr_vars.cbegin(); i != curr_vars.cend(); ++i)
        {
            SetEnvironmentVariableA(i->first.c_str(), NULL);
        }
    }

    for (auto i = options.environmentVars.cbegin(); i != options.environmentVars.cend(); ++i) {
        SetEnvironmentVariableA(i->first.c_str(), i->second.c_str());
    }

    return curr_vars;
}
Result<Environment> Environment::CreateForUser(const Handle& token, bool inherit, Trace& trace)
{
	trace < L"Environment::CreateForUser";
	Environment newEnvironment;
	LPVOID environment;
	if (!CreateEnvironmentBlock(&environment, token, inherit))
	{
		return Result<Environment>(ErrorUtilities::GetErrorCode(), ErrorUtilities::GetLastErrorMessage(L"CreateEnvironmentBlock"));
	}

	try
	{
		newEnvironment.CreateVariableMap(environment, trace);
	}
	catch (...)
	{
	}

	DestroyEnvironmentBlock(environment);
	return newEnvironment;
}
Result<Environment> Environment::CreateForUser(const Handle& token, bool inherit, Trace& trace)
{
	trace < L"Environment::CreateForUser";
	Environment newEnvironment;
	LPVOID environment;
	if (!CreateEnvironmentBlock(&environment, token, inherit))
	{
		return Error(L"CreateEnvironmentBlock");
	}

	try
	{
		newEnvironment.CreateVariableMap(environment, trace);
	}
	catch (...)
	{
	}

	DestroyEnvironmentBlock(environment);
	return newEnvironment;
}
Example #11
0
BOOL
MSWindowsWatchdog::doStartProcess(String& command, HANDLE userToken, LPSECURITY_ATTRIBUTES sa)
{
	// clear, as we're reusing process info struct
	ZeroMemory(&m_processInfo, sizeof(PROCESS_INFORMATION));

	STARTUPINFO si;
	ZeroMemory(&si, sizeof(STARTUPINFO));
	si.cb = sizeof(STARTUPINFO);
	si.lpDesktop = "winsta0\\Default"; // TODO: maybe this should be \winlogon if we have logonui.exe?
	si.hStdError = m_stdOutWrite;
	si.hStdOutput = m_stdOutWrite;
	si.dwFlags |= STARTF_USESTDHANDLES;

	LPVOID environment;
	BOOL blockRet = CreateEnvironmentBlock(&environment, userToken, FALSE);
	if (!blockRet) {
		LOG((CLOG_ERR "could not create environment block"));
		throw XArch(new XArchEvalWindows);
	}

	DWORD creationFlags = 
		NORMAL_PRIORITY_CLASS |
		CREATE_NO_WINDOW |
		CREATE_UNICODE_ENVIRONMENT;

	// re-launch in current active user session
	LOG((CLOG_INFO "starting new process"));
	BOOL createRet = CreateProcessAsUser(
		userToken, NULL, LPSTR(command.c_str()),
		sa, NULL, TRUE, creationFlags,
		environment, NULL, &si, &m_processInfo);

	DestroyEnvironmentBlock(environment);
	CloseHandle(userToken);

	return createRet;
}
std::shared_ptr<PROCESS_INFORMATION> LaunchProcess(wchar_t* commandline, DWORD sessionid){
	auto ProcessInfo = std::shared_ptr<PROCESS_INFORMATION>(new PROCESS_INFORMATION(), [=](PROCESS_INFORMATION* p){
		CloseHandle(p->hThread);
		CloseHandle(p->hProcess);
		delete p;
	});
	STARTUPINFO StartUPInfo;
	memset(&StartUPInfo, 0, sizeof(STARTUPINFO));
	memset(ProcessInfo.get(), 0, sizeof(PROCESS_INFORMATION));

	StartUPInfo.lpDesktop = L"Winsta0\\Winlogon";
	StartUPInfo.cb = sizeof(STARTUPINFO);
	HANDLE winloginhandle = NULL;
	PVOID	lpEnvironment = NULL;

	if (GetWinlogonHandle(&winloginhandle, sessionid)){
		if (CreateEnvironmentBlock(&lpEnvironment, winloginhandle, FALSE) == FALSE) lpEnvironment = NULL;
		SetLastError(0);
		CreateProcessAsUser(winloginhandle, NULL, commandline, NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT | NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW | DETACHED_PROCESS, lpEnvironment, NULL, &StartUPInfo, ProcessInfo.get());
	}
	if (lpEnvironment) DestroyEnvironmentBlock(lpEnvironment);
	CloseHandle(winloginhandle);
	return ProcessInfo;
}
Example #13
0
void
CMSWindowsRelauncher::mainLoop(void*)
{
	shutdownExistingProcesses();

	SendSas sendSasFunc = NULL;
	HINSTANCE sasLib = LoadLibrary("sas.dll");
	if (sasLib) {
		LOG((CLOG_DEBUG "found sas.dll"));
		sendSasFunc = (SendSas)GetProcAddress(sasLib, "SendSAS");
	}

	DWORD sessionId = -1;
	bool launched = false;

	SECURITY_ATTRIBUTES saAttr; 
	saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
	saAttr.bInheritHandle = TRUE; 
	saAttr.lpSecurityDescriptor = NULL; 

	if (!CreatePipe(&m_stdOutRead, &m_stdOutWrite, &saAttr, 0)) {
		throw XArch(new XArchEvalWindows());
	}

	PROCESS_INFORMATION pi;
	ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));

	int failures = 0;

	while (m_running) {

		HANDLE sendSasEvent = 0;
		if (sasLib && sendSasFunc) {
			// can't we just create one event? seems weird creating a new
			// event every second...
			sendSasEvent = CreateEvent(NULL, FALSE, FALSE, "Global\\SendSAS");
		}

		DWORD newSessionId = getSessionId();

		bool running = false;
		if (launched) {

			DWORD exitCode;
			GetExitCodeProcess(pi.hProcess, &exitCode);
			running = (exitCode == STILL_ACTIVE);

			if (!running) {
				failures++;
				LOG((CLOG_INFO "detected application not running, pid=%d, failures=%d", pi.dwProcessId, failures));
				
				// increasing backoff period, maximum of 10 seconds.
				int timeout = (failures * 2) < 10 ? (failures * 2) : 10;
				LOG((CLOG_DEBUG "waiting, backoff period is %d seconds", timeout));
				ARCH->sleep(timeout);
				
				// double check, in case process started after we waited.
				GetExitCodeProcess(pi.hProcess, &exitCode);
				running = (exitCode == STILL_ACTIVE);
			}
			else {
				// reset failures when running.
				failures = 0;
			}
		}

		// only enter here when id changes, and the session isn't -1, which
		// may mean that there is no active session.
		bool sessionChanged = ((newSessionId != sessionId) && (newSessionId != -1));

		// relaunch if it was running but has stopped unexpectedly.
		bool stoppedRunning = (launched && !running);

		if (stoppedRunning || sessionChanged || m_commandChanged) {
			
			m_commandChanged = false;

			if (launched) {
				LOG((CLOG_DEBUG "closing existing process to make way for new one"));
				shutdownProcess(pi.hProcess, pi.dwProcessId, 20);
				launched = false;
			}

			// ok, this is now the active session (forget the old one if any)
			sessionId = newSessionId;

			SECURITY_ATTRIBUTES sa;
			ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));

			// get the token for the user in active session, which is the
			// one receiving input from mouse and keyboard.
			HANDLE userToken = getCurrentUserToken(sessionId, &sa);

			if (userToken != 0) {
				LOG((CLOG_DEBUG "got user token to launch new process"));

				std::string cmd = command();
				if (cmd == "") {
					// this appears on first launch when the user hasn't configured
					// anything yet, so don't show it as a warning, only show it as
					// debug to devs to let them know why nothing happened.
					LOG((CLOG_DEBUG "nothing to launch, no command specified."));
					continue;
				}

				// in case reusing process info struct
				ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));

				STARTUPINFO si;
				ZeroMemory(&si, sizeof(STARTUPINFO));
				si.cb = sizeof(STARTUPINFO);
				si.lpDesktop = "winsta0\\default";
				si.hStdError = m_stdOutWrite;
				si.hStdOutput = m_stdOutWrite;
				si.dwFlags |= STARTF_USESTDHANDLES;

				LPVOID environment;
				BOOL blockRet = CreateEnvironmentBlock(&environment, userToken, FALSE);
				if (!blockRet) {
					LOG((CLOG_ERR "could not create environment block (error: %i)", 
						GetLastError()));
					continue;
				}
				else {

					DWORD creationFlags = 
						NORMAL_PRIORITY_CLASS |
						CREATE_NO_WINDOW |
						CREATE_UNICODE_ENVIRONMENT;

					// re-launch in current active user session
					LOG((CLOG_INFO "starting new process"));
					BOOL createRet = CreateProcessAsUser(
						userToken, NULL, LPSTR(cmd.c_str()),
						&sa, NULL, TRUE, creationFlags,
						environment, NULL, &si, &pi);

					DestroyEnvironmentBlock(environment);
					CloseHandle(userToken);

					if (!createRet) {
						LOG((CLOG_ERR "could not launch (error: %i)", GetLastError()));
						continue;
					}
					else {
						LOG((CLOG_DEBUG "launched in session %i (cmd: %s)", 
							sessionId, cmd.c_str()));
						launched = true;
					}
				}
			}
		}

		if (sendSasEvent) {
			// use SendSAS event to wait for next session.
			if (WaitForSingleObject(sendSasEvent, 1000) == WAIT_OBJECT_0 && sendSasFunc) {
				LOG((CLOG_DEBUG "calling SendSAS"));
				sendSasFunc(FALSE);
			}
			CloseHandle(sendSasEvent);
		}
		else {
			// check for session change every second.
			ARCH->sleep(1);
		}
	}

	if (launched) {
		LOG((CLOG_DEBUG "terminated running process on exit"));
		shutdownProcess(pi.hProcess, pi.dwProcessId, 20);
	}
	
	LOG((CLOG_DEBUG "relauncher main thread finished"));
}
Example #14
0
    bool LaunchProcess(const string16& cmdline,
        const LaunchOptions& options,
        ProcessHandle* process_handle)
    {
        STARTUPINFO startup_info = {};
        startup_info.cb = sizeof(startup_info);
        if(options.empty_desktop_name)
        {
            startup_info.lpDesktop = L"";
        }
        startup_info.dwFlags = STARTF_USESHOWWINDOW;
        startup_info.wShowWindow = options.start_hidden ? SW_HIDE : SW_SHOW;
        PROCESS_INFORMATION process_info;

        DWORD flags = 0;

        if(options.job_handle)
        {
            flags |= CREATE_SUSPENDED;

            // If this code is run under a debugger, the launched process is
            // automatically associated with a job object created by the debugger.
            // The CREATE_BREAKAWAY_FROM_JOB flag is used to prevent this.
            flags |= CREATE_BREAKAWAY_FROM_JOB;
        }

        if(options.as_user)
        {
            flags |= CREATE_UNICODE_ENVIRONMENT;
            void* enviroment_block = NULL;

            if(!CreateEnvironmentBlock(&enviroment_block, options.as_user, FALSE))
            {
                return false;
            }

            BOOL launched = CreateProcessAsUser(options.as_user, NULL,
                const_cast<wchar_t*>(cmdline.c_str()),
                NULL, NULL, options.inherit_handles, flags,
                enviroment_block, NULL, &startup_info,
                &process_info);
            DestroyEnvironmentBlock(enviroment_block);
            if(!launched)
            {
                return false;
            }
        }
        else
        {
            if(!CreateProcess(NULL,
                const_cast<wchar_t*>(cmdline.c_str()), NULL, NULL,
                options.inherit_handles, flags, NULL, NULL,
                &startup_info, &process_info))
            {
                return false;
            }
        }

        if(options.job_handle)
        {
            if(0 == AssignProcessToJobObject(options.job_handle, process_info.hProcess))
            {
                LOG(ERROR) << "Could not AssignProcessToObject.";
                KillProcess(process_info.hProcess, kProcessKilledExitCode, true);
                return false;
            }

            ResumeThread(process_info.hThread);
        }

        // Handles must be closed or they will leak.
        CloseHandle(process_info.hThread);

        if(options.wait)
        {
            WaitForSingleObject(process_info.hProcess, INFINITE);
        }

        // If the caller wants the process handle, we won't close it.
        if(process_handle)
        {
            *process_handle = process_info.hProcess;
        }
        else
        {
            CloseHandle(process_info.hProcess);
        }
        return true;
    }
Example #15
0
BOOL
WinLaunchChild(const wchar_t *exePath,
               int argc,
               wchar_t **argv,
               HANDLE userToken,
               HANDLE *hProcess)
{
  wchar_t *cl;
  BOOL ok;

  cl = MakeCommandLine(argc, argv);
  if (!cl) {
    return FALSE;
  }

  STARTUPINFOW si = {0};
  si.cb = sizeof(STARTUPINFOW);
  si.lpDesktop = L"winsta0\\Default";
  PROCESS_INFORMATION pi = {0};

  if (userToken == nullptr) {
    ok = CreateProcessW(exePath,
                        cl,
                        nullptr,  // no special security attributes
                        nullptr,  // no special thread attributes
                        FALSE, // don't inherit filehandles
                        0,     // creation flags
                        nullptr,  // inherit my environment
                        nullptr,  // use my current directory
                        &si,
                        &pi);
  } else {
    // Create an environment block for the process we're about to start using
    // the user's token.
    LPVOID environmentBlock = nullptr;
    if (!CreateEnvironmentBlock(&environmentBlock, userToken, TRUE)) {
      environmentBlock = nullptr;
    }

    ok = CreateProcessAsUserW(userToken,
                              exePath,
                              cl,
                              nullptr,  // no special security attributes
                              nullptr,  // no special thread attributes
                              FALSE,    // don't inherit filehandles
                              0,        // creation flags
                              environmentBlock,
                              nullptr,  // use my current directory
                              &si,
                              &pi);

    if (environmentBlock) {
      DestroyEnvironmentBlock(environmentBlock);
    }
  }

  if (ok) {
    if (hProcess) {
      *hProcess = pi.hProcess; // the caller now owns the HANDLE
    } else {
      CloseHandle(pi.hProcess);
    }
    CloseHandle(pi.hThread);
  } else {
    LPVOID lpMsgBuf = nullptr;
    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
                  FORMAT_MESSAGE_FROM_SYSTEM |
                  FORMAT_MESSAGE_IGNORE_INSERTS,
                  nullptr,
                  GetLastError(),
                  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                  (LPTSTR) &lpMsgBuf,
                  0,
                  nullptr);
    wprintf(L"Error restarting: %s\n", lpMsgBuf ? static_cast<const wchar_t*>(lpMsgBuf) : L"(null)");
    if (lpMsgBuf)
      LocalFree(lpMsgBuf);
  }

  free(cl);

  return ok;
}
Example #16
0
/* returns TRUE if a user's environment was loaded; otherwise, FALSE.*/
BOOL
OwnerProfile::environment ( Env &env ) {

    dprintf ( D_FULLDEBUG, "In OwnerProfile::environment()\n" );

    priv_state  priv    = PRIV_UNKNOWN;
    PVOID       penv    = NULL;
    PWSTR       w_penv  = NULL,
                w_tmp   = NULL;
    PSTR        tmp     = NULL;    
    BOOL        created = FALSE,
                ok      = FALSE;

    __try {

        /* we must do the following as the user or Condor */
        priv = set_condor_priv ();

        /* if we are loading the user's profile, then overwrite 
        any existing environment variables with the values in the 
        user's profile (don't inherit anything from the global
        environment, as we will already have that at when we are 
        called) */
        created = CreateEnvironmentBlock ( 
            &penv, 
            user_token_, 
            FALSE ); /* we already have the current process env */
        ASSERT ( penv );

        dprintf ( 
            D_FULLDEBUG, 
            "OwnerProfile::environment: Loading %s while retrieving "
            "%s's environment (last-error = %u)\n",
            created ? "succeeded" : "failed", 
            user_name_,
            GetLastError () );

        if ( !created ) {
            __leave;
        }

        /* fill the environment with the user's environment values */
        dprintf ( D_FULLDEBUG, "Environment:\n" );
        w_penv = (PWSTR)penv;
        while ( '\0' != *w_penv ) { /* read: while not "\0\0' */
            tmp = ProduceAFromW ( w_penv );
            if ( tmp && strlen ( tmp ) > 0 ) {
                dprintf ( D_FULLDEBUG, "%s\n", tmp );
                env.SetEnv ( tmp );
                delete [] tmp;
            }
            w_penv += wcslen ( w_penv ) + 1;
        }

        /* if we've arrived here, then all it well */
        ok = TRUE;

    }
    __finally {

        /* rid ourselves of the user's environment information */
        if ( penv ) {
            if ( !DestroyEnvironmentBlock ( penv ) ) {
                dprintf ( 
                    D_ALWAYS, 
                    "OwnerProfile::environment: "
                    "DestroyEnvironmentBlock() failed "
                    "(last-error = %u)\n", 
                    GetLastError () );
            }
        }

        /* return to previous privilege level */
        set_priv ( priv );

    }

    return ok;

}
Example #17
0
int execute(const std::wstring& commandLine, const commandlineProcessor& options)
{
    wchar_t * environment = nullptr;
    HANDLE userToken = INVALID_HANDLE_VALUE;

    if (options.e)
    {
        OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &userToken);
        CreateEnvironmentBlock(
            reinterpret_cast<LPVOID *>(&environment),
            userToken,
            FALSE
        );
        CloseHandle(userToken);
    }


    BOOL noError;
    STARTUPINFO startupInfo;
    PROCESS_INFORMATION processInformation;
    ZeroMemory(&startupInfo, sizeof(startupInfo));
    startupInfo.cb = sizeof(startupInfo);
    startupInfo.dwFlags = STARTF_USESHOWWINDOW;
    startupInfo.wShowWindow = SW_HIDE;
    noError = CreateProcess(
        NULL,											//lpApplicationName
        const_cast<LPWSTR>(commandLine.c_str()),		//lpCommandLine
        NULL,											//lpProcessAttributes
        NULL,											//lpThreadAttributes
        FALSE,											//bInheritHandles
        CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT,	//dwCreationFlags
        options.e ? environment : NULL,					//lpEnvironment
        NULL,											//lpCurrentDirectory
        &startupInfo,									//lpStartupInfo
        &processInformation								//lpProcessInformation
    );

    if(!noError)
    {
        return GetLastError();
    }
    
    DWORD exitCode = 0;
    
    if (options.w)
    {
        WaitForSingleObject(processInformation.hProcess, INFINITE);
        if (GetExitCodeProcess(processInformation.hProcess, &exitCode) == 0)
        {
            exitCode = (DWORD)-1;
        }
    }

    CloseHandle( processInformation.hProcess );
    CloseHandle( processInformation.hThread );
    if (options.e)
    {
        DestroyEnvironmentBlock(static_cast<LPVOID>(environment));
    }

    return (int) exitCode;
}
void
CMSWindowsRelauncher::mainLoop(void*)
{
	SendSas sendSasFunc = NULL;
	HINSTANCE sasLib = LoadLibrary("sas.dll");
	if (sasLib) {
		LOG((CLOG_DEBUG "found sas.dll"));
		sendSasFunc = (SendSas)GetProcAddress(sasLib, "SendSAS");
	}

	DWORD sessionId = -1;
	bool launched = false;

	SECURITY_ATTRIBUTES saAttr; 
	saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
	saAttr.bInheritHandle = TRUE; 
	saAttr.lpSecurityDescriptor = NULL; 

	if (!CreatePipe(&m_stdOutRead, &m_stdOutWrite, &saAttr, 0)) {
		throw XArch(new XArchEvalWindows());
	}

	PROCESS_INFORMATION pi;
	ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));

	while (m_running) {

		HANDLE sendSasEvent = 0;
		if (sasLib && sendSasFunc) {
			// can't we just create one event? seems weird creating a new
			// event every second...
			sendSasEvent = CreateEvent(NULL, FALSE, FALSE, "Global\\SendSAS");
		}

		DWORD newSessionId = getSessionId();

		// only enter here when id changes, and the session isn't -1, which
		// may mean that there is no active session.
		if (((newSessionId != sessionId) && (newSessionId != -1)) || m_commandChanged) {
			
			m_commandChanged = false;

			if (launched) {
				LOG((CLOG_DEBUG "closing existing process to make way for new one"));
				shutdownProcess(pi, 10);
				launched = false;
			}

			// ok, this is now the active session (forget the old one if any)
			sessionId = newSessionId;

			SECURITY_ATTRIBUTES sa;
			ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));

			// get the token for the user in active session, which is the
			// one receiving input from mouse and keyboard.
			HANDLE userToken = getCurrentUserToken(sessionId, &sa);

			if (userToken != 0) {
				LOG((CLOG_DEBUG "got user token to launch new process"));

				std::string cmd = command();
				if (cmd == "") {
					LOG((CLOG_WARN "nothing to launch, no command specified."));
					continue;
				}

				// in case reusing process info struct
				ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));

				STARTUPINFO si;
				ZeroMemory(&si, sizeof(STARTUPINFO));
				si.cb = sizeof(STARTUPINFO);
				si.lpDesktop = "winsta0\\default";
				si.hStdError = m_stdOutWrite;
				si.hStdOutput = m_stdOutWrite;
				si.dwFlags |= STARTF_USESTDHANDLES;

				LPVOID environment;
				BOOL blockRet = CreateEnvironmentBlock(&environment, userToken, FALSE);
				if (!blockRet) {
					LOG((CLOG_ERR "could not create environment block (error: %i)", 
						GetLastError()));
					continue;
				}
				else {

					DWORD creationFlags = 
						NORMAL_PRIORITY_CLASS |
						CREATE_NO_WINDOW |
						CREATE_UNICODE_ENVIRONMENT;

					// re-launch in current active user session
					BOOL createRet = CreateProcessAsUser(
						userToken, NULL, LPSTR(cmd.c_str()),
						&sa, NULL, TRUE, creationFlags,
						environment, NULL, &si, &pi);

					DestroyEnvironmentBlock(environment);
					CloseHandle(userToken);

					if (!createRet) {
						LOG((CLOG_ERR "could not launch (error: %i)", GetLastError()));
						continue;
					}
					else {
						LOG((CLOG_DEBUG "launched in session %i (cmd: %s)", 
							sessionId, cmd.c_str()));
						launched = true;
					}
				}
			}
		}

		if (sendSasEvent) {
			// use SendSAS event to wait for next session.
			if (WaitForSingleObject(sendSasEvent, 1000) == WAIT_OBJECT_0 && sendSasFunc) {
				LOG((CLOG_DEBUG "calling SendSAS"));
				sendSasFunc(FALSE);
			}
			CloseHandle(sendSasEvent);
		}
		else {
			// check for session change every second.
			ARCH->sleep(1);
		}
	}

	if (launched) {
		LOG((CLOG_DEBUG "terminated running process on exit"));
		shutdownProcess(pi, 10);
	}
}
Example #19
0
bool StartProcess(Settings& settings, HANDLE hCmdPipe)
{
	//Launching as one of:
	//1. System Account
	//2. Specified account (or limited account)
	//3. As current process

	DWORD gle = 0;

	BOOL bLoadedProfile = FALSE;
	PROFILEINFO profile = {0};
	profile.dwSize = sizeof(profile);
	profile.lpUserName = (LPWSTR)(LPCWSTR)settings.user;
	profile.dwFlags = PI_NOUI;

	if(false == GetUserHandle(settings, bLoadedProfile, profile, hCmdPipe))
		return false;

	PROCESS_INFORMATION pi = {0};
	STARTUPINFO si = {0};
	si.cb = sizeof(si);
	si.dwFlags = STARTF_USESHOWWINDOW;
	si.wShowWindow = SW_SHOW;
	if(!BAD_HANDLE(settings.hStdErr))
	{
		si.hStdError = settings.hStdErr;
		si.hStdInput = settings.hStdIn;
		si.hStdOutput = settings.hStdOut;
		si.dwFlags |= STARTF_USESTDHANDLES;
#ifdef _DEBUG
		Log(L"DEBUG: Using redirected handles", false);
#endif
	}
#ifdef _DEBUG
	else
		Log(L"DEBUG: Not using redirected IO", false);
#endif

	CString path = StrFormat(L"\"%s\"", settings.app);
	if(FALSE == settings.appArgs.IsEmpty())
	{
		path += L" ";
		path += settings.appArgs;
	}

	LPCWSTR startingDir = NULL;
	if(FALSE == settings.workingDir.IsEmpty())
		startingDir = settings.workingDir;

	DWORD launchGLE = 0;

	CleanupInteractive ci = {0};

	if(settings.bInteractive || settings.bShowUIOnWinLogon)
	{
		BOOL b = PrepForInteractiveProcess(settings, &ci, settings.sessionToInteractWith);
		if(FALSE == b)
			Log(L"Failed to PrepForInteractiveProcess", true);

		if(NULL == si.lpDesktop)
			si.lpDesktop = L"WinSta0\\Default"; 
		if(settings.bShowUIOnWinLogon)
			si.lpDesktop = L"winsta0\\Winlogon";
		//Log(StrFormat(L"Using desktop: %s", si.lpDesktop), false);
		//http://blogs.msdn.com/b/winsdk/archive/2009/07/14/launching-an-interactive-process-from-windows-service-in-windows-vista-and-later.aspx
		//indicates desktop names are case sensitive
	}
#ifdef _DEBUG
	Log(StrFormat(L"DEBUG: PAExec using desktop %s", si.lpDesktop == NULL ? L"{default}" : si.lpDesktop), false);
#endif

	DWORD dwFlags = CREATE_SUSPENDED | CREATE_NEW_CONSOLE;

	LPVOID pEnvironment = NULL;
	VERIFY(CreateEnvironmentBlock(&pEnvironment, settings.hUser, TRUE));
	if(NULL != pEnvironment)
		dwFlags |= CREATE_UNICODE_ENVIRONMENT;
#ifdef _DEBUG
	gle = GetLastError();
	Log(L"DEBUG: CreateEnvironmentBlock", gle);
#endif

	if(settings.bDisableFileRedirection)
		DisableFileRedirection();

	if(settings.bRunLimited)
		if(false == LimitRights(settings.hUser))
			return false;

	if(settings.bRunElevated)
		if(false == ElevateUserToken(settings.hUser))
			return false;

	CString user, domain;
	GetUserDomain(settings.user, user, domain);

#ifdef _DEBUG
	Log(StrFormat(L"DEBUG: U:%s D:%s P:%s bP:%d Env:%s WD:%s",
		user, domain, settings.password, settings.bDontLoadProfile,
		pEnvironment ? L"true" : L"null", startingDir ? startingDir : L"null"), false);
#endif

	BOOL bLaunched = FALSE;

	if(settings.bUseSystemAccount)
	{
		Log(StrFormat(L"PAExec starting process [%s] as Local System", path), false);

		if(BAD_HANDLE(settings.hUser))
			Log(L"Have bad user handle", true);

		EnablePrivilege(SE_IMPERSONATE_NAME);
		BOOL bImpersonated = ImpersonateLoggedOnUser(settings.hUser);
		if(FALSE == bImpersonated)
		{
			Log(L"Failed to impersonate", GetLastError());
			_ASSERT(bImpersonated);
		}
		EnablePrivilege(SE_ASSIGNPRIMARYTOKEN_NAME);
		EnablePrivilege(SE_INCREASE_QUOTA_NAME);
		bLaunched = CreateProcessAsUser(settings.hUser, NULL, path.LockBuffer(), NULL, NULL, TRUE, dwFlags, pEnvironment, startingDir, &si, &pi);
		launchGLE = GetLastError();
		path.UnlockBuffer();

#ifdef _DEBUG
		if(0 != launchGLE)
			Log(StrFormat(L"Launch (launchGLE=%u) params: user=[x%X] path=[%s] flags=[x%X], pEnv=[%s], dir=[%s], stdin=[x%X], stdout=[x%X], stderr=[x%X]",
						launchGLE, (DWORD)settings.hUser, path, dwFlags, pEnvironment ? L"{env}" : L"{null}", startingDir ? startingDir : L"{null}", 
						(DWORD)si.hStdInput, (DWORD)si.hStdOutput, (DWORD)si.hStdError), false);
#endif

		RevertToSelf();
	}
	else
	{
		if(FALSE == settings.user.IsEmpty()) //launching as a specific user
		{
			Log(StrFormat(L"PAExec starting process [%s] as %s", path, settings.user), false);

			if(false == settings.bRunLimited)
			{
				bLaunched = CreateProcessWithLogonW(user, domain.IsEmpty() ? NULL : domain, settings.password, settings.bDontLoadProfile ? 0 : LOGON_WITH_PROFILE, NULL, path.LockBuffer(), dwFlags, pEnvironment, startingDir, &si, &pi);
				launchGLE = GetLastError();
				path.UnlockBuffer();

#ifdef _DEBUG
				if(0 != launchGLE) 
					Log(StrFormat(L"Launch (launchGLE=%u) params: user=[%s] domain=[%s] prof=[x%X] path=[%s] flags=[x%X], pEnv=[%s], dir=[%s], stdin=[x%X], stdout=[x%X], stderr=[x%X]",
									launchGLE, user, domain, settings.bDontLoadProfile ? 0 : LOGON_WITH_PROFILE, 
									path, dwFlags, pEnvironment ? L"{env}" : L"{null}", startingDir ? startingDir : L"{null}", 
									(DWORD)si.hStdInput, (DWORD)si.hStdOutput, (DWORD)si.hStdError), false);
#endif
			}
			else
				bLaunched = FALSE; //force to run with CreateProcessAsUser so rights can be limited

			//CreateProcessWithLogonW can't be called from LocalSystem on Win2003 and earlier, so LogonUser/CreateProcessAsUser must be used. Might as well try for everyone
			if((FALSE == bLaunched) && !BAD_HANDLE(settings.hUser))
			{
#ifdef _DEBUG
				Log(L"DEBUG: Failed CreateProcessWithLogonW - trying CreateProcessAsUser", GetLastError());
#endif
				EnablePrivilege(SE_ASSIGNPRIMARYTOKEN_NAME);
				EnablePrivilege(SE_INCREASE_QUOTA_NAME);
				EnablePrivilege(SE_IMPERSONATE_NAME);
				BOOL bImpersonated = ImpersonateLoggedOnUser(settings.hUser);
				if(FALSE == bImpersonated)
				{
					Log(L"Failed to impersonate", GetLastError());
					_ASSERT(bImpersonated);
				}

				bLaunched = CreateProcessAsUser(settings.hUser, NULL, path.LockBuffer(), NULL, NULL, TRUE, CREATE_SUSPENDED | CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_CONSOLE, pEnvironment, startingDir, &si, &pi);
				if(0 == GetLastError())
					launchGLE = 0; //mark as successful, otherwise return our original error
				path.UnlockBuffer();
#ifdef _DEBUG
				if(0 != launchGLE)
					Log(StrFormat(L"Launch (launchGLE=%u) params: user=[x%X] path=[%s] pEnv=[%s], dir=[%s], stdin=[x%X], stdout=[x%X], stderr=[x%X]",
									launchGLE, (DWORD)settings.hUser, path, pEnvironment ? L"{env}" : L"{null}", startingDir ? startingDir : L"{null}", 
									(DWORD)si.hStdInput, (DWORD)si.hStdOutput, (DWORD)si.hStdError), false);
#endif
				RevertToSelf();
			}
		}
		else
		{
			Log(StrFormat(L"PAExec starting process [%s] as current user", path), false);

			EnablePrivilege(SE_ASSIGNPRIMARYTOKEN_NAME);
			EnablePrivilege(SE_INCREASE_QUOTA_NAME);
			EnablePrivilege(SE_IMPERSONATE_NAME);

			if(NULL != settings.hUser)
				bLaunched = CreateProcessAsUser(settings.hUser, NULL, path.LockBuffer(), NULL, NULL, TRUE, dwFlags, pEnvironment, startingDir, &si, &pi);
			if(FALSE == bLaunched)
				bLaunched = CreateProcess(NULL, path.LockBuffer(), NULL, NULL, TRUE, dwFlags, pEnvironment, startingDir, &si, &pi);
			launchGLE = GetLastError();
	
//#ifdef _DEBUG
			if(0 != launchGLE)
				Log(StrFormat(L"Launch (launchGLE=%u) params: path=[%s] user=[%s], pEnv=[%s], dir=[%s], stdin=[x%X], stdout=[x%X], stderr=[x%X]",
					launchGLE, path, settings.hUser ? L"{non-null}" : L"{null}", pEnvironment ? L"{env}" : L"{null}", startingDir ? startingDir : L"{null}", 
					(DWORD)si.hStdInput, (DWORD)si.hStdOutput, (DWORD)si.hStdError), false);
//#endif
			path.UnlockBuffer();
		}
	}

	if(bLaunched)
	{
		if(gbInService)
			Log(L"Successfully launched", false);

		settings.hProcess = pi.hProcess;
		settings.processID = pi.dwProcessId;

		if(false == settings.allowedProcessors.empty())
		{
			DWORD sysMask = 0, procMask = 0;
			VERIFY(GetProcessAffinityMask(pi.hProcess, &procMask, &sysMask));
			procMask = 0;
			for(std::vector<WORD>::iterator itr = settings.allowedProcessors.begin(); settings.allowedProcessors.end() != itr; itr++)
			{
				DWORD bit = 1;
				bit = bit << (*itr - 1);
				procMask |= bit & sysMask;
			}
			VERIFY(SetProcessAffinityMask(pi.hProcess, procMask));
		}

		VERIFY(SetPriorityClass(pi.hProcess, settings.priority));
		ResumeThread(pi.hThread);
		VERIFY(CloseHandle(pi.hThread));
	}
	else
	{
		Log(StrFormat(L"Failed to start %s.", path), launchGLE);
		if((ERROR_ELEVATION_REQUIRED == launchGLE) && (false == gbInService))
			Log(L"HINT: PAExec probably needs to be \"Run As Administrator\"", false);
	}

	if(ci.bPreped)
		CleanUpInteractiveProcess(&ci);

	if(settings.bDisableFileRedirection)
		RevertFileRedirection();

	if(NULL != pEnvironment)
		DestroyEnvironmentBlock(pEnvironment);
	pEnvironment = NULL;

	if(bLoadedProfile)
		UnloadUserProfile(settings.hUser, profile.hProfile);

	if(!BAD_HANDLE(settings.hUser))
	{
		CloseHandle(settings.hUser);
		settings.hUser = NULL;
	}

	return bLaunched ? true : false;
}
Example #20
0
BOOL CreateInteractiveProcess(DWORD dwSessionId,
                              PWSTR pszCommandLine, 
                              BOOL fWait, 
                              DWORD dwTimeout, 
                              DWORD *pExitCode)
{
    DWORD dwError = ERROR_SUCCESS;
    HANDLE hToken = NULL;
    LPVOID lpvEnv = NULL;
    wchar_t szUserProfileDir[MAX_PATH];
    DWORD cchUserProfileDir = ARRAYSIZE(szUserProfileDir);
    STARTUPINFO si = { sizeof(si) };
    PROCESS_INFORMATION pi = { 0 };
    DWORD dwWaitResult;

    // Obtain the primary access token of the logged-on user specified by the 
    // session ID.
    if (!WTSQueryUserToken(dwSessionId, &hToken))
    {
        dwError = GetLastError();
        goto Cleanup;
    }

    // Run the command line in the session that we found by using the default 
    // values for working directory and desktop.

    // This creates the default environment block for the user.
    if (!CreateEnvironmentBlock(&lpvEnv, hToken, TRUE))
    {
        dwError = GetLastError();
        goto Cleanup;
    }

    // Retrieve the path to the root directory of the user's profile.
    if (!GetUserProfileDirectory(hToken, szUserProfileDir, 
        &cchUserProfileDir))
    {
        dwError = GetLastError();
        goto Cleanup;
    }

    // Specify that the process runs in the interactive desktop.
    si.lpDesktop = L"winsta0\\default";

    // Launch the process.
    if (!CreateProcessAsUser(hToken, NULL, pszCommandLine, NULL, NULL, FALSE, 
        CREATE_UNICODE_ENVIRONMENT, lpvEnv, szUserProfileDir, &si, &pi))
    {
        dwError = GetLastError();
        goto Cleanup;
    }

    if (fWait)
    {
        // Wait for the exit of the process.
        dwWaitResult = WaitForSingleObject(pi.hProcess, dwTimeout);
        if (dwWaitResult == WAIT_OBJECT_0)
        {
            // If the process exits before timeout, get the exit code.
            GetExitCodeProcess(pi.hProcess, pExitCode);
        }
        else if (dwWaitResult == WAIT_TIMEOUT)
        {
            // If it times out, terminiate the process.
            TerminateProcess(pi.hProcess, IDTIMEOUT);
            *pExitCode = IDTIMEOUT;
        }
        else
        {
            dwError = GetLastError();
            goto Cleanup;
        }
    }
    else
    {
        *pExitCode = IDASYNC;
    }

Cleanup:

    // Centralized cleanup for all allocated resources.
    if (hToken)
    {
        CloseHandle(hToken);
        hToken = NULL;
    }
    if (lpvEnv)
    {
        DestroyEnvironmentBlock(lpvEnv);
        lpvEnv = NULL;
    }
    if (pi.hProcess)
    {
        CloseHandle(pi.hProcess);
        pi.hProcess = NULL;
    }
    if (pi.hThread)
    {
        CloseHandle(pi.hThread);
        pi.hThread = NULL;
    }

    // Set the last error if something failed in the function.
    if (dwError != ERROR_SUCCESS)
    {
        SetLastError(dwError);
        return FALSE;
    }
    else
    {
        return TRUE;
    }
}
Example #21
0
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// START the app as system 
BOOL
LaunchProcessWin(DWORD dwSessionId,bool preconnect)
{
  BOOL                 bReturn = FALSE;
  HANDLE               hToken;
  STARTUPINFO          StartUPInfo;
  PVOID                lpEnvironment = NULL;

  ZeroMemory(&StartUPInfo,sizeof(STARTUPINFO));
  ZeroMemory(&ProcessInfo,sizeof(PROCESS_INFORMATION));
  StartUPInfo.wShowWindow = SW_SHOW;
  //StartUPInfo.lpDesktop = "Winsta0\\Winlogon";
  StartUPInfo.lpDesktop = "Winsta0\\Default";
  StartUPInfo.cb = sizeof(STARTUPINFO);
  SetTBCPrivileges();
  pad2(preconnect);

  if ( GetSessionUserTokenWin(&hToken,dwSessionId) )
  {
      if ( CreateEnvironmentBlock(&lpEnvironment, hToken, FALSE) ) 
      {
      
		 SetLastError(0);
         if (CreateProcessAsUser(hToken,NULL,app_path,NULL,NULL,FALSE,CREATE_UNICODE_ENVIRONMENT |DETACHED_PROCESS,lpEnvironment,NULL,&StartUPInfo,&ProcessInfo))
			{
				counter=0;
				bReturn = TRUE;
				DWORD error=GetLastError();
				#ifdef _DEBUG
					char			szText[256];
					sprintf(szText," ++++++ CreateProcessAsUser winlogon %d\n",error);
					OutputDebugString(szText);		
				#endif
			}
		 else
		 {
			 DWORD error=GetLastError();
			 #ifdef _DEBUG
					char			szText[256];
					sprintf(szText," ++++++ CreateProcessAsUser failed %d %d %d\n",error,kickrdp,counter);
					OutputDebugString(szText);		
			#endif
			if (error==233 && kickrdp==1)
					{
						counter++;
						if (counter>3)
							{
								#ifdef _DEBUG
								DWORD error=GetLastError();
								sprintf(szText," ++++++ error==233 win\n");
								SetLastError(0);
								OutputDebugString(szText);		
								#endif
								typedef BOOLEAN (WINAPI * pWinStationConnect) (HANDLE,ULONG,ULONG,PCWSTR,ULONG);
								typedef BOOL (WINAPI * pLockWorkStation)();
								HMODULE  hlibwinsta = LoadLibrary("winsta.dll"); 
								HMODULE  hlibuser32 = LoadLibrary("user32.dll");
								pWinStationConnect WinStationConnectF=NULL;
								pLockWorkStation LockWorkStationF=NULL;

								if (hlibwinsta)
								   {
									   WinStationConnectF=(pWinStationConnect)GetProcAddress(hlibwinsta, "WinStationConnectW"); 
								   }
								if (hlibuser32)
								   {
									   LockWorkStationF=(pLockWorkStation)GetProcAddress(hlibuser32, "LockWorkStation"); 
								   }
								if (WinStationConnectF!=NULL && LockWorkStationF!=NULL)
									{
											DWORD ID=0;
											if (lpfnWTSGetActiveConsoleSessionId.isValid()) ID=(*lpfnWTSGetActiveConsoleSessionId)();
											WinStationConnectF(0, 0, ID, L"", 0);
											LockWorkStationF();
									}
								Sleep(3000);
						}
					}
			else if (error==233)
			{
				CreateRemoteSessionProcess(dwSessionId,true,hToken,NULL,app_path,NULL,NULL,FALSE,CREATE_UNICODE_ENVIRONMENT |DETACHED_PROCESS,lpEnvironment,NULL,&StartUPInfo,&ProcessInfo);
				counter=0;
				bReturn = TRUE;
			}
		 }

         if (lpEnvironment) 
         {
            DestroyEnvironmentBlock(lpEnvironment);
         }

	  }//createenv
	  else
	  {
		  SetLastError(0);
         if (CreateProcessAsUser(hToken,NULL,app_path,NULL,NULL,FALSE,DETACHED_PROCESS,NULL,NULL,&StartUPInfo,&ProcessInfo))
			{
				counter=0;
				bReturn = TRUE;
				DWORD error=GetLastError();
				#ifdef _DEBUG
					char			szText[256];
					sprintf(szText," ++++++ CreateProcessAsUser winlogon %d\n",error);
					OutputDebugString(szText);		
				#endif
			}
		 else
		 {
			 DWORD error=GetLastError();
			 #ifdef _DEBUG
					char			szText[256];
					sprintf(szText," ++++++ CreateProcessAsUser no env failed %d\n",error);
					OutputDebugString(szText);		
			#endif
			//Little trick needed, FUS sometimes has an unreachable logon session.
			 //Switch to USER B, logout user B
			 //The logon session is then unreachable
			 //We force the logon session on the console
			if (error==233 && kickrdp==1)
					{
						counter++;
						if (counter>3)
							{
								#ifdef _DEBUG
								DWORD error=GetLastError();
								sprintf(szText," ++++++ error==233 win\n");
								SetLastError(0);
								OutputDebugString(szText);		
								#endif
								typedef BOOLEAN (WINAPI * pWinStationConnect) (HANDLE,ULONG,ULONG,PCWSTR,ULONG);
								typedef BOOL (WINAPI * pLockWorkStation)();
								HMODULE  hlibwinsta = LoadLibrary("winsta.dll"); 
								HMODULE  hlibuser32 = LoadLibrary("user32.dll");
								pWinStationConnect WinStationConnectF=NULL;
								pLockWorkStation LockWorkStationF=NULL;

								if (hlibwinsta)
								   {
									   WinStationConnectF=(pWinStationConnect)GetProcAddress(hlibwinsta, "WinStationConnectW"); 
								   }
								if (hlibuser32)
								   {
									   LockWorkStationF=(pLockWorkStation)GetProcAddress(hlibuser32, "LockWorkStation"); 
								   }
								if (WinStationConnectF!=NULL && LockWorkStationF!=NULL)
									{
											DWORD ID=0;
											if (lpfnWTSGetActiveConsoleSessionId.isValid()) ID=(*lpfnWTSGetActiveConsoleSessionId)();
											WinStationConnectF(0, 0, ID, L"", 0);
											LockWorkStationF();
									}
								Sleep(3000);
						}
			}
			else if (error==233)
			{
				CreateRemoteSessionProcess(dwSessionId,true,hToken,NULL,app_path,NULL,NULL,FALSE,DETACHED_PROCESS,NULL,NULL,&StartUPInfo,&ProcessInfo);
				counter=0;
				bReturn = TRUE;
			}
	  }
        
	}  //getsession
	CloseHandle(hToken);
	}
  else
  {
	 #ifdef _DEBUG
	char			szText[256];
	DWORD error=GetLastError();
	sprintf(szText," ++++++ Getsessionusertokenwin failed %d\n",error);
	OutputDebugString(szText);		
	#endif

  }
    
    return bReturn;
}
Example #22
0
//Function to run a process as active user from windows service
bool ActiveUserAndRun(std::wstring sUser, std::wstring sPassword, std::wstring sDomain, std::wstring sCommand)
{
	bool bResult = false;

	HANDLE hImpersonationToken = NULL;
	int nTick = ::GetTickCount();
	if (LoginBasedOnUserAccount(sUser, sPassword, sDomain, hImpersonationToken) == false)
	{
		std::cout << "Cannot login toolbox server" << std::endl;
		return false;
	}

	std::cout << "Take tickcount: " << (::GetTickCount() - nTick) << std::endl;
	// raise priv
	//enable_privs(hImpersonationToken);

	std::cout << "Before DuplicateTokenEx " << std::endl;
	HANDLE hUserToken = NULL;

	if (!DuplicateTokenEx(hImpersonationToken,
		//0,
		//MAXIMUM_ALLOWED,
		TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS | MAXIMUM_ALLOWED,
		NULL,
		SecurityImpersonation,
		TokenPrimary,
		&hUserToken))
	{
		//log error
		std::cout << "DuplicateTokenEx, error: " << ::GetLastError() << std::endl;
		return false;
	}

	std::cout << "DuplicateTokenEx successfully" << std::endl;

	STARTUPINFO StartupInfo = {0};  
	PROCESS_INFORMATION processInfo = {0};  

	StartupInfo.cb = sizeof(STARTUPINFO);  
	//std::string command = "HRAUnsolicitedAdapter.exe";
	LPVOID lpEnvironment = NULL;
	if (!CreateEnvironmentBlock(&lpEnvironment, hUserToken, TRUE))  
	{  
		std::cout << "CreateEnvironmentBlock failed! Error: " << ::GetLastError() << std::endl;
		return false;
	}  

	bResult = CreateProcessAsUser(  
		hUserToken,   
		0,   
		(LPWSTR)sCommand.c_str(),   
		NULL,   
		NULL,   
		FALSE,   
		NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT,  
		lpEnvironment, // __in_opt    LPVOID lpEnvironment,  
		0,   
		&StartupInfo,   
		&processInfo);  


	DestroyEnvironmentBlock(lpEnvironment);

	CloseHandle(hImpersonationToken);
	CloseHandle(hUserToken);

	RevertToSelf();

	// log off


	std::cout << "WTSFreeMemory done" << std::endl;

	return bResult;
}