Guest User

Untitled

a guest
Feb 19th, 2018
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.80 KB | None | 0 0
  1. public class UnManagedProcess : IProcess
  2. {
  3. private IntPtr _userToken;
  4. private IntPtr _duplicatedUserToken;
  5. private ProcessInformation _processInfo;
  6. private StartupInfo _startupInfo;
  7. private SecurityAttributes _securityAttributes;
  8. private ProfileInfo _profileInfo;
  9. private readonly ProcessStartInfo _processStartInfo;
  10. private readonly int _creationFlags;
  11. private readonly TimeSpan? _timeOut;
  12. private readonly List<string> _arguments;
  13. private readonly UnManagedEnvironmentVariables _environments;
  14.  
  15.  
  16. public bool RedirectStandardError => false;
  17.  
  18. public bool RedirectStandardOutput => false;
  19.  
  20. public bool IsExited { get; private set; }
  21.  
  22. public int ExitCode { get; private set; }
  23.  
  24. public DateTime StartTime { get; private set; }
  25.  
  26. public DateTime ExitTime { get; private set; }
  27.  
  28. public bool IsInterrupted { get; private set; }
  29.  
  30. public int ErrorCode { get; private set; }
  31.  
  32. public UnManagedProcess(Script script)
  33. {
  34. _processStartInfo = new ProcessInfoBuilder().FileName(script.FileName).AddEnvironmentVariables(script.Arguments).WithUsersCredentials(script.Login, script.Password, script.Domain).Create();
  35.  
  36. _processInfo = new ProcessInformation();
  37. _userToken = IntPtr.Zero;
  38. _duplicatedUserToken = IntPtr.Zero;
  39.  
  40. _securityAttributes = new SecurityAttributes();
  41. _securityAttributes.Length = Marshal.SizeOf(_securityAttributes);
  42.  
  43. _startupInfo = new StartupInfo();
  44. _startupInfo.cb = Marshal.SizeOf(_startupInfo);
  45. _startupInfo.lpDesktop = string.Empty;
  46.  
  47. _creationFlags = (int) (CreationFlags.CreateUnicodeEnvironment | CreationFlags.CreateNoWindow);
  48.  
  49. _profileInfo = new ProfileInfo();
  50. _profileInfo.dwSize = Marshal.SizeOf(_profileInfo);
  51. _profileInfo.lpUserName = _processStartInfo.UserName;
  52. _profileInfo.dwFlags = 1;
  53.  
  54. if (!script.WaitForever)
  55. {
  56. _timeOut = TimeSpan.FromSeconds(script.TimeOutInSeconds);
  57. }
  58.  
  59. _arguments = script.Arguments;
  60.  
  61. _environments = new UnManagedEnvironmentVariables();
  62. }
  63.  
  64. public async Task StartAsync()
  65. {
  66. StartTime = DateTime.Now;
  67. StartProcess();
  68. var waitTask = new Task(WaitProcess);
  69. waitTask.Start();
  70. try
  71. {
  72. if (_timeOut != null)
  73. {
  74. await waitTask.TimeoutAfter(_timeOut.Value);
  75. }
  76. else
  77. {
  78. await waitTask;
  79. }
  80. }
  81. catch (TimeoutException)
  82. {
  83. IsInterrupted = true;
  84. KillProcess();
  85. }
  86.  
  87. ExitTime = DateTime.Now;
  88. }
  89.  
  90. public Task<string> ReadAllFromStandardErrorAsync(TimeSpan timeOut)
  91. {
  92. return Task.FromResult(string.Empty);
  93. }
  94.  
  95. public Task<string> ReadAllFromStandardOutputAsync(TimeSpan timeOut)
  96. {
  97. return Task.FromResult(string.Empty);
  98. }
  99.  
  100. public void Dispose()
  101. {
  102. if (_userToken != IntPtr.Zero)
  103. CloseHandle(_userToken);
  104. if (_duplicatedUserToken != IntPtr.Zero)
  105. CloseHandle(_duplicatedUserToken);
  106. if (_processInfo.hProcess != IntPtr.Zero)
  107. CloseHandle(_processInfo.hProcess);
  108. if (_processInfo.hThread != IntPtr.Zero)
  109. CloseHandle(_processInfo.hThread);
  110. }
  111.  
  112. private void StartProcess()
  113. {
  114. LogOnUser(_processStartInfo.UserName, _processStartInfo.Domain, _processStartInfo.PasswordInClearText);
  115. DuplicateToken();
  116. FillEnvironment();
  117. LoadUserProfile();
  118. var arguments = "/c" + " " + _processStartInfo.FileName;
  119. CreateProcess("C:\\windows\\System32\\cmd.exe", arguments, _environments.GetEnvironmentBlock());
  120. }
  121.  
  122. private void CreateProcess(string fileName, string arguments, IntPtr environment)
  123. {
  124. var successful = CreateProcessAsUser(_duplicatedUserToken,
  125. fileName,
  126. arguments,
  127. ref _securityAttributes,
  128. ref _securityAttributes,
  129. false,
  130. _creationFlags,
  131. environment,
  132. _processStartInfo.WorkingDirectory,
  133. ref _startupInfo,
  134. ref _processInfo);
  135. ThrowIfError(successful);
  136. }
  137.  
  138. private void LoadUserProfile()
  139. {
  140. var successful = Win32ProcessUtility.LoadUserProfile(_duplicatedUserToken, ref _profileInfo);
  141. ThrowIfError(successful);
  142. }
  143.  
  144. private void DuplicateToken()
  145. {
  146. var successful = DuplicateTokenEx(_userToken,
  147. GenericAllAccess,
  148. ref _securityAttributes,
  149. (int) SecurityImpersonationLevel.SecurityIdentification,
  150. (int) TokenType.TokenPrimary,
  151. ref _duplicatedUserToken);
  152. ThrowIfError(successful);
  153. }
  154.  
  155. private void LogOnUser(string name, string domain, string password)
  156. {
  157. var successful = LogonUser(name,
  158. domain,
  159. password,
  160. LOGON32_LOGON_INTERACTIVE,
  161. LOGON32_PROVIDER_DEFAULT,
  162. ref _userToken) != 0;
  163. ThrowIfError(successful);
  164. }
  165.  
  166. private void FillEnvironment()
  167. {
  168. var successful = _environments.ReadEnvironmentBlock(_userToken);
  169. if (_arguments != null)
  170. {
  171. foreach (var argument in _arguments)
  172. {
  173. var pair = argument.Split(new[] {'='}, 2);
  174. _environments.Add(pair[0], pair[1]);
  175. }
  176. }
  177.  
  178. ThrowIfError(successful);
  179. }
  180.  
  181.  
  182. private void WaitProcess()
  183. {
  184. var result = WaitForSingleObject(_processInfo.hProcess, Infinite);
  185. switch ((WaitForSingleObjectResult) result)
  186. {
  187. case WaitForSingleObjectResult.WaitObject0:
  188. IsExited = true;
  189. ExitCode = GetExitCode();
  190. break;
  191. case WaitForSingleObjectResult.WaitTimeout:
  192. IsExited = true;
  193. IsInterrupted = true;
  194. KillProcess();
  195. ExitCode = GetExitCode();
  196. break;
  197. case WaitForSingleObjectResult.WaitFailed:
  198. IsExited = false;
  199. IsInterrupted = true;
  200. throw new Win32Exception(Marshal.GetLastWin32Error());
  201. case WaitForSingleObjectResult.WaitAbandoned:
  202. break;
  203. default:
  204. throw new ArgumentOutOfRangeException();
  205. }
  206. }
  207.  
  208. private void KillProcess()
  209. {
  210. var successful = TerminateProcess(_processInfo.hProcess, 1);
  211. ThrowIfError(successful);
  212. ExitCode = GetExitCode();
  213. }
  214.  
  215. private int GetExitCode()
  216. {
  217. var successful = GetExitCodeProcess(_processInfo.hProcess, out var result);
  218. ThrowIfError(successful);
  219. return (int) result;
  220. }
  221.  
  222. private void ThrowIfError(bool successful)
  223. {
  224. if (successful) return;
  225. ErrorCode = Marshal.GetLastWin32Error();
  226. throw new Win32Exception(ErrorCode);
  227. }
  228.  
  229.  
  230. internal class UnManagedEnvironmentVariables
  231. {
  232. private static readonly string Format = "{0}={1}";
  233. private static readonly char[] SplitSymb = {'='};
  234.  
  235.  
  236. private Dictionary<string, string> Variables { get; }
  237.  
  238. public UnManagedEnvironmentVariables()
  239. {
  240. Variables = new Dictionary<string, string>();
  241. }
  242.  
  243. public bool ReadEnvironmentBlock(IntPtr userToken)
  244. {
  245. var successful = CreateEnvironmentBlock(out var environmentBlock, userToken, false);
  246. var startPosition = environmentBlock;
  247. if (successful)
  248. {
  249. while (true)
  250. {
  251. var value = Marshal.PtrToStringUni(startPosition);
  252. if (string.IsNullOrEmpty(value))
  253. break;
  254.  
  255. var pair = value.Split(SplitSymb, 2);
  256. Variables.Add(pair[0], pair[1]);
  257.  
  258. startPosition = startPosition + (value.Length + 1) * sizeof(char);
  259. }
  260.  
  261. DestroyEnvironmentBlock(environmentBlock);
  262. }
  263.  
  264. return successful;
  265. }
  266.  
  267. public IntPtr GetEnvironmentBlock()
  268. {
  269. var stringEnv = string.Join("\0", Variables.Select(pair => string.Format(Format, pair.Key, pair.Value))) + "\0\0\0\0";
  270. return Marshal.StringToHGlobalUni(stringEnv);
  271. }
  272.  
  273. public void Add(string key, string value)
  274. {
  275. Variables.Add(key, value);
  276. }
  277. }
  278. }
Add Comment
Please, Sign In to add comment