private Win32EnvironmentBlock CreateEnvironmentBlockForUser(WindowsIdentity useridentity, string username, string profilePath) { Win32EnvironmentBlock eb = Win32EnvironmentBlock.Create(useridentity.Token); _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariableCreationBegin, username, profilePath); // if broker and rhost are run as different users recreate user environment variables. eb["USERNAME"] = username; _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "USERNAME", eb["USERNAME"]); eb["HOMEDRIVE"] = profilePath.Substring(0, 2); _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "HOMEDRIVE", eb["HOMEDRIVE"]); eb["HOMEPATH"] = profilePath.Substring(2); _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "HOMEPATH", eb["HOMEPATH"]); eb["USERPROFILE"] = $"{eb["HOMEDRIVE"]}{eb["HOMEPATH"]}"; _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "USERPROFILE", eb["USERPROFILE"]); eb["APPDATA"] = $"{eb["USERPROFILE"]}\\AppData\\Roaming"; _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "APPDATA", eb["APPDATA"]); eb["LOCALAPPDATA"] = $"{eb["USERPROFILE"]}\\AppData\\Local"; _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "LOCALAPPDATA", eb["LOCALAPPDATA"]); eb["TEMP"] = $"{eb["LOCALAPPDATA"]}\\Temp"; _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "TEMP", eb["TEMP"]); eb["TMP"] = $"{eb["LOCALAPPDATA"]}\\Temp"; _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "TMP", eb["TMP"]); return(eb); }
private void AddGlobalREnvironmentVariables(Win32EnvironmentBlock eb) { // Get the broker's environment block var brokerEb = Win32EnvironmentBlock.Create(WindowsIdentity.GetCurrent().Token); foreach (var e in brokerEb) { if (e.Key.StartsWithOrdinal("R_")) { eb[e.Key] = e.Value; } } }
public IProcess StartHost(Interpreter interpreter, string profilePath, string userName, WindowsIdentity useridentity, string commandLine) { string brokerPath = Path.GetDirectoryName(typeof(Program).Assembly.GetAssemblyPath()); string rhostExePath = Path.Combine(brokerPath, RHostExe); commandLine = FormattableString.Invariant($"\"{rhostExePath}\" {commandLine}"); var usernameBldr = new StringBuilder(NativeMethods.CREDUI_MAX_USERNAME_LENGTH + 1); var domainBldr = new StringBuilder(NativeMethods.CREDUI_MAX_DOMAIN_LENGTH + 1); // Get R_HOME value var shortHome = new StringBuilder(NativeMethods.MAX_PATH); NativeMethods.GetShortPathName(interpreter.Info.Path, shortHome, shortHome.Capacity); var loggedOnUser = useridentity != null && WindowsIdentity.GetCurrent().User != useridentity.User; // build user environment block Win32EnvironmentBlock eb; if (loggedOnUser) { uint error = NativeMethods.CredUIParseUserName(userName, usernameBldr, usernameBldr.Capacity, domainBldr, domainBldr.Capacity); if (error != 0) { _sessionLogger.LogError(Resources.Error_UserNameParse, userName, error); throw new ArgumentException(Resources.Error_UserNameParse.FormatInvariant(userName, error)); } string username = usernameBldr.ToString(); string domain = domainBldr.ToString(); eb = CreateEnvironmentBlockForUser(useridentity, username, profilePath); } else { eb = Win32EnvironmentBlock.Create((useridentity ?? WindowsIdentity.GetCurrent()).Token); } // add additional variables to the environment block eb["R_HOME"] = shortHome.ToString(); _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "R_HOME", eb["R_HOME"]); eb["PATH"] = FormattableString.Invariant($"{interpreter.Info.BinPath};{Environment.GetEnvironmentVariable("PATH")}"); _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "PATH", eb["PATH"]); Win32Process win32Process; using (Win32NativeEnvironmentBlock nativeEnv = eb.GetNativeEnvironmentBlock()) { if (loggedOnUser) { win32Process = Win32Process.StartProcessAsUser(useridentity, rhostExePath, commandLine, Path.GetDirectoryName(rhostExePath), nativeEnv); } else { win32Process = Win32Process.StartProcessAsUser(null, rhostExePath, commandLine, Path.GetDirectoryName(rhostExePath), nativeEnv); } } win32Process.WaitForExit(250); if (win32Process.HasExited && win32Process.ExitCode < 0) { var message = ErrorCodeConverter.MessageFromErrorCode(win32Process.ExitCode); if (!string.IsNullOrEmpty(message)) { throw new Win32Exception(message); } throw new Win32Exception(win32Process.ExitCode); } return(win32Process); }
public void StartHost(string profilePath, string logFolder, ILogger outputLogger, LogVerbosity verbosity) { if (_hostEnd != null) { throw new InvalidOperationException("Host process is already running"); } var useridentity = User as WindowsIdentity; // In remote broker User Identity type is always WindowsIdentity string suppressUI = (useridentity == null) ? string.Empty : "--rhost-suppress-ui "; string isRepl = _isInteractive ? "--rhost-interactive " : string.Empty; string brokerPath = Path.GetDirectoryName(typeof(Program).Assembly.GetAssemblyPath()); string rhostExePath = Path.Combine(brokerPath, RHostExe); string logFolderParam = string.IsNullOrEmpty(logFolder) ? string.Empty : Invariant($"--rhost-log-dir \"{logFolder}\""); string commandLine = Invariant($"\"{rhostExePath}\" {suppressUI}{isRepl}--rhost-name \"{Id}\" {logFolderParam} --rhost-log-verbosity {(int)verbosity} {CommandLineArguments}"); var usernameBldr = new StringBuilder(NativeMethods.CREDUI_MAX_USERNAME_LENGTH + 1); var domainBldr = new StringBuilder(NativeMethods.CREDUI_MAX_DOMAIN_LENGTH + 1); // Get R_HOME value var shortHome = new StringBuilder(NativeMethods.MAX_PATH); NativeMethods.GetShortPathName(Interpreter.Info.Path, shortHome, shortHome.Capacity); Stream stdout, stdin, stderror; bool loggedOnUser = useridentity != null && WindowsIdentity.GetCurrent().User != useridentity.User; // build user environment block Win32EnvironmentBlock eb; if (loggedOnUser) { uint error = NativeMethods.CredUIParseUserName(User.Name, usernameBldr, usernameBldr.Capacity, domainBldr, domainBldr.Capacity); if (error != 0) { _sessionLogger.LogError(Resources.Error_UserNameParse, User.Name, error); throw new ArgumentException(Resources.Error_UserNameParse.FormatInvariant(User.Name, error)); } string username = usernameBldr.ToString(); string domain = domainBldr.ToString(); eb = CreateEnvironmentBlockForUser(useridentity, username, profilePath); } else { eb = Win32EnvironmentBlock.Create((useridentity ?? WindowsIdentity.GetCurrent()).Token); } // add additional variables to the environment block eb["R_HOME"] = shortHome.ToString(); _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "R_HOME", eb["R_HOME"]); eb["PATH"] = Invariant($"{Interpreter.Info.BinPath};{Environment.GetEnvironmentVariable("PATH")}"); _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "PATH", eb["PATH"]); _sessionLogger.LogInformation(Resources.Info_StartingRHost, Id, User.Name, commandLine); using (Win32NativeEnvironmentBlock nativeEnv = eb.GetNativeEnvironmentBlock()) { if (loggedOnUser) { _process = Win32Process.StartProcessAsUser(useridentity, rhostExePath, commandLine, Path.GetDirectoryName(rhostExePath), nativeEnv, out stdin, out stdout, out stderror); } else { _process = Win32Process.StartProcessAsUser(null, rhostExePath, commandLine, Path.GetDirectoryName(rhostExePath), nativeEnv, out stdin, out stdout, out stderror); } } _process.Exited += delegate(object o, Win32ProcessExitEventArgs exitState){ _hostEnd?.Dispose(); _hostEnd = null; State = SessionState.Terminated; if (exitState.HasError()) { _sessionLogger.LogInformation(Resources.Error_ExitRHost, exitState.ExitCode); } }; _process.WaitForExit(250); if (_process.HasExited && _process.ExitCode < 0) { var message = ErrorCodeConverter.MessageFromErrorCode(_process.ExitCode); if (!string.IsNullOrEmpty(message)) { throw new Win32Exception(message); } throw new Win32Exception(_process.ExitCode); } _sessionLogger.LogInformation(Resources.Info_StartedRHost, Id, User.Name); var hostEnd = _pipe.ConnectHost(_process.ProcessId); _hostEnd = hostEnd; ClientToHostWorker(stdin, hostEnd).DoNotWait(); HostToClientWorker(stdout, hostEnd).DoNotWait(); HostToClientErrorWorker(stderror, _process.ProcessId, (int processid, string errdata) => { outputLogger?.LogTrace(Resources.Trace_ErrorDataReceived, processid, errdata); }).DoNotWait(); }