protected override void Dispose(bool disposing)
 {
     _stdinReadHandle.Dispose();
     _stdinWriteHandle.Dispose();
     _stdoutReadHandle.Dispose();
     _stdoutWriteHandle.Dispose();
     _stderrReadHandle.Dispose();
     _stderrWriteHandle.Dispose();
     if (_processHandle != null)
     {
         _processHandle.Dispose();
     }
     base.Dispose(disposing);
 }
Example #2
0
        private Win32Process(NativeMethods.PROCESS_INFORMATION pi, StreamWriter stdin, StreamReader stdout, StreamReader stderror)
        {
            StandardInput  = stdin;
            StandardOutput = stdout;
            StandardError  = stderror;
            _hasExited     = false;
            _exitCodeLock  = new object();
            Id             = pi.dwProcessId;
            MainThreadId   = pi.dwThreadId;
            _processHandle = new SafeProcessHandle(pi.hProcess, true);

            var wait = new ProcessWaitHandle(_processHandle);

            _registeredWait = ThreadPool.RegisterWaitForSingleObject(wait, (o, t) => {
                _registeredWait.Unregister(wait);
                SetExitState();
                Exited?.Invoke(this, EventArgs.Empty);
                _processHandle.Dispose();
                wait.Dispose();
            }, null, -1, true);

            _disposable
            .Add(() => _registeredWait.Unregister(wait))
            .Add(_processHandle)
            .Add(wait);
        }
Example #3
0
        /// <summary>
        /// Instructs the Process component to wait the specified number of milliseconds for the associated process to exit.
        /// </summary>
        private bool WaitForExitCore(int milliseconds)
        {
            SafeProcessHandle handle = null;

            try
            {
                handle = GetProcessHandle(Interop.Advapi32.ProcessOptions.SYNCHRONIZE, false);
                if (handle.IsInvalid)
                {
                    return(true);
                }

                using (Interop.Kernel32.ProcessWaitHandle processWaitHandle = new Interop.Kernel32.ProcessWaitHandle(handle))
                {
                    return(_signaled = processWaitHandle.WaitOne(milliseconds));
                }
            }
            finally
            {
                // If we have a hard timeout, we cannot wait for the streams
                if (_output != null && milliseconds == Timeout.Infinite)
                {
                    _output.WaitUtilEOF();
                }

                if (_error != null && milliseconds == Timeout.Infinite)
                {
                    _error.WaitUtilEOF();
                }

                handle?.Dispose();
            }
        }
        public static SafeProcessHandle OpenProcess(int processId, int access, bool throwIfExited)
        {
            SafeProcessHandle processHandle = Interop.Kernel32.OpenProcess(access, false, processId);
            int result = Marshal.GetLastWin32Error();

            if (!processHandle.IsInvalid)
            {
                return(processHandle);
            }

            processHandle.Dispose();

            if (processId == 0)
            {
                throw new Win32Exception(Interop.Errors.ERROR_ACCESS_DENIED);
            }

            // If the handle is invalid because the process has exited, only throw an exception if throwIfExited is true.
            // Assume the process is still running if the error was ERROR_ACCESS_DENIED for better performance
            if (result != Interop.Errors.ERROR_ACCESS_DENIED && !IsProcessRunning(processId))
            {
                if (throwIfExited)
                {
                    throw new InvalidOperationException(SR.Format(SR.ProcessHasExited, processId.ToString()));
                }
                else
                {
                    return(SafeProcessHandle.InvalidHandle);
                }
            }
            throw new Win32Exception(result);
        }
Example #5
0
 internal static void KillTree(int processIdTokill)
 {
     using (Process process = Process.GetProcessById(processIdTokill))
     {
         DateTime          startTime = process.StartTime;
         SafeProcessHandle handle    = OpenProcess(eDesiredAccess.PROCESS_QUERY_INFORMATION, false, processIdTokill);
         if (!handle.IsInvalid)
         {
             try
             {
                 process.Kill();
                 List <Tuple <int, SafeProcessHandle> > childProcessIds = GetChildProcessIds(processIdTokill, startTime);
                 try
                 {
                     foreach (Tuple <int, SafeProcessHandle> tuple in childProcessIds)
                     {
                         KillTree(tuple.Item1);
                     }
                 }
                 finally
                 {
                     foreach (Tuple <int, SafeProcessHandle> tuple2 in childProcessIds)
                     {
                         tuple2.Item2.Dispose();
                     }
                 }
             }
             finally
             {
                 handle.Dispose();
             }
         }
     }
 }
Example #6
0
        [Fact, PlatformSpecific(PlatformID.Windows), OuterLoop] // Requires admin privileges
        public void TestUserCredentialsPropertiesOnWindows()
        {
            string username = "******", password = "******";

            try
            {
                Interop.NetUserAdd(username, password);
            }
            catch (Exception exc)
            {
                Console.Error.WriteLine("TestUserCredentialsPropertiesOnWindows: NetUserAdd failed: {0}", exc.Message);
                return; // test is irrelevant if we can't add a user
            }

            Process p = CreateProcessLong();

            p.StartInfo.LoadUserProfile     = true;
            p.StartInfo.UserName            = username;
            p.StartInfo.PasswordInClearText = password;

            SafeProcessHandle handle = null;

            try
            {
                p.Start();
                if (Interop.OpenProcessToken(p.SafeHandle, 0x8u, out handle))
                {
                    SecurityIdentifier sid;
                    if (Interop.ProcessTokenToSid(handle, out sid))
                    {
                        string actualUserName = sid.Translate(typeof(NTAccount)).ToString();
                        int    indexOfDomain  = actualUserName.IndexOf('\\');
                        if (indexOfDomain != -1)
                        {
                            actualUserName = actualUserName.Substring(indexOfDomain + 1);
                        }

                        bool isProfileLoaded = GetNamesOfUserProfiles().Any(profile => profile.Equals(username));

                        Assert.Equal(username, actualUserName);
                        Assert.True(isProfileLoaded);
                    }
                }
            }
            finally
            {
                if (handle != null)
                {
                    handle.Dispose();
                }

                if (!p.HasExited)
                {
                    p.Kill();
                }

                Interop.NetUserDel(null, username);
                Assert.True(p.WaitForExit(WaitInMS));
            }
        }
Example #7
0
 public bool CloseHandle()
 {
     if (!IsHandleClosed)
     {
         using (SafeProcessHandle processHandle =
                    NativeMethods.OpenProcess(ProcessAccessRights.PROCESS_ALL_ACCESS,
                                              false, SourceProcess))
         {
             if (!processHandle.IsInvalid)
             {
                 SafeObjectHandle objectHandle = null;
                 if (NativeMethods.DuplicateHandle(processHandle.DangerousGetHandle(),
                                                   SourceHandle,
                                                   IntPtr.Zero,
                                                   out objectHandle,
                                                   0,
                                                   false,
                                                   DuplicateHandleOptions.DUPLICATE_CLOSE_SOURCE))
                 {
                     NativeMethods.CloseHandle(processHandle.DangerousGetHandle());
                     processHandle.Dispose();
                     IsHandleClosed = true;
                 }
             }
         }
     }
     return(IsHandleClosed);
 }
Example #8
0
 internal static void KillTree(int processIdTokill)
 {
     using (Process process = Process.GetProcessById(processIdTokill))
     {
         DateTime          startTime = process.StartTime;
         SafeProcessHandle handle    = OpenProcess(eDesiredAccess.PROCESS_QUERY_INFORMATION, false, processIdTokill);
         if (!handle.IsInvalid)
         {
             try
             {
                 process.Kill();
                 List <KeyValuePair <int, SafeProcessHandle> > childProcessIds = GetChildProcessIds(processIdTokill, startTime);
                 try
                 {
                     foreach (KeyValuePair <int, SafeProcessHandle> pair in childProcessIds)
                     {
                         KillTree(pair.Key);
                     }
                 }
                 finally
                 {
                     foreach (KeyValuePair <int, SafeProcessHandle> pair2 in childProcessIds)
                     {
                         pair2.Value.Dispose();
                     }
                 }
             }
             finally
             {
                 handle.Dispose();
             }
         }
     }
 }
Example #9
0
        /// <summary>
        /// Returns the parent process id for the specified process.
        /// Returns zero if it cannot be gotten for some reason.
        /// </summary>
        internal static int GetParentProcessId(int processId)
        {
            int ParentID = 0;
            SafeProcessHandle hProcess = OpenProcess(eDesiredAccess.PROCESS_QUERY_INFORMATION, false, processId);

            if (!hProcess.IsInvalid)
            {
                try
                {
                    // UNDONE: NtQueryInformationProcess will fail if we are not elevated and other process is. Advice is to change to use ToolHelp32 API's
                    // For now just return zero and worst case we will not kill some children.
                    PROCESS_BASIC_INFORMATION pbi = new PROCESS_BASIC_INFORMATION();
                    int pSize = 0;

                    if (0 == NtQueryInformationProcess(hProcess, PROCESSINFOCLASS.ProcessBasicInformation, ref pbi, pbi.Size, ref pSize))
                    {
                        ParentID = (int)pbi.InheritedFromUniqueProcessId;
                    }
                }
                finally
                {
                    hProcess.Dispose();
                }
            }

            return(ParentID);
        }
Example #10
0
 public void Dispose()
 {
     if (!isDisposed)
     {
         isDisposed = true;
         CloseStreams();
         ClosePipes();
         proc?.Dispose();
     }
 }
Example #11
0
        public void Dispose()
        {
            foreach (var peInstance in _peInstances)
            {
                peInstance.Value.Dispose();
            }

            Process.Dispose();

            Handle.Dispose();
        }
Example #12
0
        /// <summary>
        /// Releases resources associated to this object.
        /// </summary>
        public void Dispose()
        {
            if (!_isDisposed)
            {
                _processHandle.Dispose();
                _waitHandle.Dispose();
                _standardInput?.Dispose();
                _standardOutput?.Dispose();
                _standardError?.Dispose();

                _isDisposed = true;
            }
        }
Example #13
0
 public void Dispose()
 {
     if (safeProcessHandle != null)
     {
         safeProcessHandle.Dispose();
     }
     if (standardOutput != null)
     {
         standardOutput.Dispose();
     }
     if (standardError != null)
     {
         standardError.Dispose();
     }
 }
Example #14
0
        /// <summary>
        /// Returns an array of all the immediate child processes by id.
        /// NOTE: The IntPtr in the tuple is the handle of the child process.  CloseHandle MUST be called on this.
        /// </summary>
        private static List <KeyValuePair <int, SafeProcessHandle> > GetChildProcessIds(int parentProcessId, DateTime parentStartTime)
        {
            List <KeyValuePair <int, SafeProcessHandle> > myChildren = new List <KeyValuePair <int, SafeProcessHandle> >();

            foreach (Process possibleChildProcess in Process.GetProcesses())
            {
                using (possibleChildProcess)
                {
                    // Hold the child process handle open so that children cannot die and restart with a different parent after we've started looking at it.
                    // This way, any handle we pass back is guaranteed to be one of our actual children.
                    SafeProcessHandle childHandle = OpenProcess(eDesiredAccess.PROCESS_QUERY_INFORMATION, false, possibleChildProcess.Id);
                    if (childHandle.IsInvalid)
                    {
                        continue;
                    }

                    bool keepHandle = false;
                    try
                    {
                        if (possibleChildProcess.StartTime > parentStartTime)
                        {
                            int childParentProcessId = GetParentProcessId(possibleChildProcess.Id);
                            if (childParentProcessId != 0)
                            {
                                if (parentProcessId == childParentProcessId)
                                {
                                    // Add this one
                                    myChildren.Add(new KeyValuePair <int, SafeProcessHandle>(possibleChildProcess.Id, childHandle));
                                    keepHandle = true;
                                }
                            }
                        }
                    }
                    finally
                    {
                        if (!keepHandle)
                        {
                            childHandle.Dispose();
                        }
                    }
                }
            }

            return(myChildren);
        }
Example #15
0
        private List <(Process Process, SafeProcessHandle Handle)> GetProcessHandlePairs(Func <Process, Process, bool> predicate)
        {
            var results = new List <(Process Process, SafeProcessHandle Handle)>();

            foreach (Process p in GetProcesses())
            {
                SafeProcessHandle h = SafeGetHandle(p);
                if (!h.IsInvalid && predicate(this, p))
                {
                    results.Add((p, h));
                }
                else
                {
                    p.Dispose();
                    h.Dispose();
                }
            }

            return(results);
        public void Dispose()
        {
            _processHandle.Dispose();
            _exitedWaitHandle.Dispose();

            if (!_isPseudoConsoleDisposed)
            {
                // This will terminate the process tree (unless we are on Windows 1809).
                _pseudoConsole?.Dispose();

                if (WindowsVersion.NeedsWorkaroundForWindows1809)
                {
                    // Should always succeed.
                    Kill();
                }

                _isPseudoConsoleDisposed = true;
            }
        }
        /// <summary>
        /// Calls <see cref="CreateProcessAsUserW"/> and safely stores the obtained handles.
        /// </summary>
        /// <param name="userToken">Token to impersonate the external process</param>
        /// <param name="createFlags">Flags used to create the external process</param>
        /// <param name="startupInfo">Startup information used to create the external process</param>
        /// <returns><c>true</c> if the call to <see cref="CreateProcessAsUserW"/> was successful; otherwise <c>false</c></returns>
        private bool SafeCreateProcessAsUserW(IntPtr userToken, CreateProcessFlags createFlags, StartupInfo startupInfo)
        {
            _processHandle = new SafeProcessHandle();
            var  threadHandle = new SafeThreadHandle();
            bool success;

            // The following is necessary to make sure that processInformation.hProcess and processInformation.hThread
            // are safely stored in the respective SafeHandle classes. It is, unfortunately, not possible to define
            // processInformation.hProcess and processInformation.hThread as SafeHandles and use processInformation
            // as an out parameter, because the unmanaged code is not able to create these objects. We therefore use
            // IntPtr and ensure in the following that the IntPtrs are stored in SafeHandle objects immediately after
            // they have been obtained.
            // For details see here: https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.runtimehelpers.prepareconstrainedregions(v=vs.110).aspx
            RuntimeHelpers.PrepareConstrainedRegions();
            try { }
            finally
            {
                ProcessInformation processInformation;
                success = CreateProcessAsUserW(userToken, null, GetCommandLine(), IntPtr.Zero, IntPtr.Zero, true, createFlags, IntPtr.Zero, null, startupInfo, out processInformation);
                if (success)
                {
                    _processHandle.InitialSetHandle(processInformation.hProcess);
                    threadHandle.InitialSetHandle(processInformation.hThread);
                    _processId = processInformation.dwProcessId;
                }
            }

            // We don't need the threadHandle and therefore immediately dispose it.
            threadHandle.Dispose();

            if (success)
            {
                return(true);
            }

            _processHandle.Dispose();
            var error = Marshal.GetLastWin32Error();

            _debugLogger.Error("AsyncImpersonationProcess ({0}): Cannot start process. ErrorCode: {1} ({2})", StartInfo.FileName, error, new Win32Exception(error).Message);
            return(false);
        }
Example #18
0
        /// <summary>
        /// Assigns a process to an existing job object.
        /// </summary>
        /// <param name="processHandle">A handle to the process to associate with the job object. The handle
        /// must have PROCESS_SET_QUOTA and PROCESS_TERMINATE access rights.</param>
        public void AssignProcess(SafeProcessHandle processHandle)
        {
            if (processHandle == null)
            {
                throw new ArgumentNullException(nameof(processHandle));
            }

            if ((processHandle.IsClosed) || (processHandle.IsInvalid))
            {
                throw new ArgumentException(Resources.ProcessHandleClosedOrInvalid);
            }

            CheckDisposed();

            SafeProcessHandle newProcessHandle = null;

            try
            {
                if (!Interop.Kernel32.DuplicateHandle(Interop.Kernel32.GetCurrentProcessIntPtr(),
                                                      processHandle,
                                                      Interop.Kernel32.GetCurrentProcessIntPtr(),
                                                      out newProcessHandle,
                                                      Interop.ProcessAccess.SetQuota | Interop.ProcessAccess.Terminate,
                                                      false,
                                                      0))
                {
                    throw Errors.Win32Error();
                }

                if (!Interop.Kernel32.AssignProcessToJobObject(Handle, newProcessHandle))
                {
                    throw Errors.Win32Error();
                }
            }
            finally
            {
                newProcessHandle?.Dispose();
            }
        }
Example #19
0
        internal static int GetParentProcessId(int processId)
        {
            int inheritedFromUniqueProcessId = 0;
            SafeProcessHandle hProcess       = OpenProcess(eDesiredAccess.PROCESS_QUERY_INFORMATION, false, processId);

            if (!hProcess.IsInvalid)
            {
                try
                {
                    PROCESS_BASIC_INFORMATION pbi = new PROCESS_BASIC_INFORMATION();
                    int pSize = 0;
                    if (-1 != NtQueryInformationProcess(hProcess, PROCESSINFOCLASS.ProcessBasicInformation, ref pbi, pbi.Size, ref pSize))
                    {
                        inheritedFromUniqueProcessId = pbi.InheritedFromUniqueProcessId;
                    }
                }
                finally
                {
                    hProcess.Dispose();
                }
            }
            return(inheritedFromUniqueProcessId);
        }
Example #20
0
        internal static List <KeyValuePair <int, SafeProcessHandle> > GetChildProcessIds(int parentProcessId, DateTime parentStartTime)
        {
            List <KeyValuePair <int, SafeProcessHandle> > list = new List <KeyValuePair <int, SafeProcessHandle> >();

            foreach (Process process in Process.GetProcesses())
            {
                using (process)
                {
                    SafeProcessHandle handle = OpenProcess(eDesiredAccess.PROCESS_QUERY_INFORMATION, false, process.Id);
                    if (!handle.IsInvalid)
                    {
                        bool flag = false;
                        try
                        {
                            if (process.StartTime > parentStartTime)
                            {
                                int num2 = GetParentProcessId(process.Id);
                                if ((num2 != 0) && (parentProcessId == num2))
                                {
                                    list.Add(new KeyValuePair <int, SafeProcessHandle>(process.Id, handle));
                                    flag = true;
                                }
                            }
                        }
                        finally
                        {
                            if (!flag)
                            {
                                handle.Dispose();
                            }
                        }
                    }
                }
            }
            return(list);
        }
        private IntPtr GetAbsoluteFunctionAddress(SafeProcessHandle hProcess, IntPtr hModule, string functionName)
        {
            var moduleInfo = GetModuleInfo(hProcess, hModule);

            DataDirectory exportDir = GetDataDirectory(ReadPage(hProcess, moduleInfo.BaseOfDll), 0);

            var buffer = new byte[exportDir.Size];

            if (!Interop.Kernel32.ReadProcessMemory(
                    hProcess,
                    moduleInfo.BaseOfDll + (int)exportDir.Rva,
                    buffer,
                    new UIntPtr((uint)buffer.Length),
                    out UIntPtr bytesRead) || bytesRead.ToUInt32() != buffer.Length)
            {
                throw new Win32Exception("Failed to read export table from memory of module.");
            }

            // We no longer need the process handle, so close it.
            hProcess.Dispose();

            return(new IntPtr(moduleInfo.BaseOfDll.ToInt64() +
                              GetFunctionAddress(buffer, exportDir.Rva, functionName).ToInt64()));
        }
Example #22
0
        /// <devdoc>
        ///    <para>
        ///       Frees any resources associated with this component.
        ///    </para>
        /// </devdoc>
        public void Close()
        {
            if (Associated)
            {
                if (_haveProcessHandle)
                {
                    // We need to lock to ensure we don't run concurrently with CompletionCallback.
                    // Without this lock we could reset _raisedOnExited which causes CompletionCallback to
                    // raise the Exited event a second time for the same process.
                    lock (this)
                    {
                        // This sets _waitHandle to null which causes CompletionCallback to not emit events.
                        StopWatchingForExit();
                    }
                    _processHandle.Dispose();
                    _processHandle     = null;
                    _haveProcessHandle = false;
                }
                _haveProcessId   = false;
                _isRemoteMachine = false;
                _machineName     = ".";
                _raisedOnExited  = false;

                // Only call close on the streams if the user cannot have a reference on them.
                // If they are referenced it is the user's responsibility to dispose of them.
                try
                {
                    if (_standardOutput != null && (_outputStreamReadMode == StreamReadMode.AsyncMode || _outputStreamReadMode == StreamReadMode.Undefined))
                    {
                        if (_outputStreamReadMode == StreamReadMode.AsyncMode)
                        {
                            _output.CancelOperation();
                        }
                        _standardOutput.Close();
                    }

                    if (_standardError != null && (_errorStreamReadMode == StreamReadMode.AsyncMode || _errorStreamReadMode == StreamReadMode.Undefined))
                    {
                        if (_errorStreamReadMode == StreamReadMode.AsyncMode)
                        {
                            _error.CancelOperation();
                        }
                        _standardError.Close();
                    }

                    if (_standardInput != null && !_standardInputAccessed)
                    {
                        _standardInput.Close();
                    }
                }
                finally
                {
                    _standardOutput = null;
                    _standardInput  = null;
                    _standardError  = null;

                    _output = null;
                    _error  = null;

                    CloseCore();
                    Refresh();
                }
            }
        }
        private static ProcessModuleCollection GetModules(int processId, bool firstModuleOnly)
        {
            // preserving Everett behavior.
            if (processId == SystemProcessID || processId == IdleProcessID)
            {
                // system process and idle process doesn't have any modules
                throw new Win32Exception(HResults.E_FAIL, SR.EnumProcessModuleFailed);
            }

            SafeProcessHandle processHandle = SafeProcessHandle.InvalidHandle;

            try
            {
                processHandle = ProcessManager.OpenProcess(processId, Interop.Advapi32.ProcessOptions.PROCESS_QUERY_INFORMATION | Interop.Advapi32.ProcessOptions.PROCESS_VM_READ, true);

                bool succeeded = Interop.Kernel32.EnumProcessModules(processHandle, null, 0, out int needed);

                // The API we need to use to enumerate process modules differs on two factors:
                //   1) If our process is running in WOW64.
                //   2) The bitness of the process we wish to introspect.
                //
                // If we are not running in WOW64 or we ARE in WOW64 but want to inspect a 32 bit process
                // we can call psapi!EnumProcessModules.
                //
                // If we are running in WOW64 and we want to inspect the modules of a 64 bit process then
                // psapi!EnumProcessModules will return false with ERROR_PARTIAL_COPY (299).  In this case we can't
                // do the enumeration at all.  So we'll detect this case and bail out.
                if (!succeeded)
                {
                    if (!Interop.Kernel32.IsWow64Process(Interop.Kernel32.GetCurrentProcess(), out bool sourceProcessIsWow64))
                    {
                        throw new Win32Exception();
                    }

                    if (!Interop.Kernel32.IsWow64Process(processHandle, out bool targetProcessIsWow64))
                    {
                        throw new Win32Exception();
                    }

                    if (sourceProcessIsWow64 && !targetProcessIsWow64)
                    {
                        // Wow64 isn't going to allow this to happen, the best we can do is give a descriptive error to the user.
                        throw new Win32Exception(Interop.Errors.ERROR_PARTIAL_COPY, SR.EnumProcessModuleFailedDueToWow);
                    }

                    EnumProcessModulesUntilSuccess(processHandle, null, 0, out needed);
                }

                int      modulesCount  = needed / IntPtr.Size;
                IntPtr[] moduleHandles = new IntPtr[modulesCount];
                while (true)
                {
                    int size = needed;
                    EnumProcessModulesUntilSuccess(processHandle, moduleHandles, size, out needed);
                    if (size == needed)
                    {
                        break;
                    }

                    if (needed > size && needed / IntPtr.Size > modulesCount)
                    {
                        modulesCount  = needed / IntPtr.Size;
                        moduleHandles = new IntPtr[modulesCount];
                    }
                }

                var modules = new ProcessModuleCollection(firstModuleOnly ? 1 : modulesCount);

                char[] chars = ArrayPool <char> .Shared.Rent(1024);

                try
                {
                    for (int i = 0; i < modulesCount; i++)
                    {
                        if (i > 0)
                        {
                            // If the user is only interested in the main module, break now.
                            // This avoid some waste of time. In addition, if the application unloads a DLL
                            // we will not get an exception.
                            if (firstModuleOnly)
                            {
                                break;
                            }
                        }

                        IntPtr moduleHandle = moduleHandles[i];
                        Interop.Kernel32.NtModuleInfo ntModuleInfo;
                        if (!Interop.Kernel32.GetModuleInformation(processHandle, moduleHandle, out ntModuleInfo))
                        {
                            HandleLastWin32Error();
                            continue;
                        }

                        var module = new ProcessModule()
                        {
                            ModuleMemorySize  = ntModuleInfo.SizeOfImage,
                            EntryPointAddress = ntModuleInfo.EntryPoint,
                            BaseAddress       = ntModuleInfo.BaseOfDll
                        };

                        int length = Interop.Kernel32.GetModuleBaseName(processHandle, moduleHandle, chars, chars.Length);
                        if (length == 0)
                        {
                            HandleLastWin32Error();
                            continue;
                        }

                        module.ModuleName = new string(chars, 0, length);

                        length = Interop.Kernel32.GetModuleFileNameEx(processHandle, moduleHandle, chars, chars.Length);
                        if (length == 0)
                        {
                            HandleLastWin32Error();
                            continue;
                        }

                        module.FileName = (length >= 4 && chars[0] == '\\' && chars[1] == '\\' && chars[2] == '?' && chars[3] == '\\') ?
                                          new string(chars, 4, length - 4) :
                                          new string(chars, 0, length);

                        modules.Add(module);
                    }
                }
                finally
                {
                    ArrayPool <char> .Shared.Return(chars);
                }

                return(modules);
            }
            finally
            {
                if (!processHandle.IsInvalid)
                {
                    processHandle.Dispose();
                }
            }
        }
Example #24
0
        private static ModuleInfo[] GetModuleInfos(int processId, bool firstModuleOnly)
        {
            Contract.Ensures(Contract.Result <ModuleInfo[]>().Length >= 1);

            // preserving Everett behavior.
            if (processId == SystemProcessID || processId == IdleProcessID)
            {
                // system process and idle process doesn't have any modules
                throw new Win32Exception(Interop.EFail, SR.EnumProcessModuleFailed);
            }

            SafeProcessHandle processHandle = SafeProcessHandle.InvalidHandle;

            try
            {
                processHandle = ProcessManager.OpenProcess(processId, Interop.PROCESS_QUERY_INFORMATION | Interop.PROCESS_VM_READ, true);

                IntPtr[] moduleHandles            = new IntPtr[64];
                GCHandle moduleHandlesArrayHandle = new GCHandle();
                int      moduleCount = 0;
                for (; ;)
                {
                    bool enumResult = false;
                    try
                    {
                        moduleHandlesArrayHandle = GCHandle.Alloc(moduleHandles, GCHandleType.Pinned);
                        enumResult = Interop.mincore.EnumProcessModules(processHandle, moduleHandlesArrayHandle.AddrOfPinnedObject(), moduleHandles.Length * IntPtr.Size, ref moduleCount);

                        // The API we need to use to enumerate process modules differs on two factors:
                        //   1) If our process is running in WOW64.
                        //   2) The bitness of the process we wish to introspect.
                        //
                        // If we are not running in WOW64 or we ARE in WOW64 but want to inspect a 32 bit process
                        // we can call psapi!EnumProcessModules.
                        //
                        // If we are running in WOW64 and we want to inspect the modules of a 64 bit process then
                        // psapi!EnumProcessModules will return false with ERROR_PARTIAL_COPY (299).  In this case we can't
                        // do the enumeration at all.  So we'll detect this case and bail out.
                        //
                        // Also, EnumProcessModules is not a reliable method to get the modules for a process.
                        // If OS loader is touching module information, this method might fail and copy part of the data.
                        // This is no easy solution to this problem. The only reliable way to fix this is to
                        // suspend all the threads in target process. Of course we don't want to do this in Process class.
                        // So we just to try avoid the race by calling the same method 50 (an arbitary number) times.
                        //
                        if (!enumResult)
                        {
                            bool sourceProcessIsWow64     = false;
                            bool targetProcessIsWow64     = false;
                            SafeProcessHandle hCurProcess = SafeProcessHandle.InvalidHandle;
                            try
                            {
                                hCurProcess = ProcessManager.OpenProcess(unchecked ((int)Interop.mincore.GetCurrentProcessId()), Interop.PROCESS_QUERY_INFORMATION, true);
                                bool wow64Ret;

                                wow64Ret = Interop.mincore.IsWow64Process(hCurProcess, ref sourceProcessIsWow64);
                                if (!wow64Ret)
                                {
                                    throw new Win32Exception();
                                }

                                wow64Ret = Interop.mincore.IsWow64Process(processHandle, ref targetProcessIsWow64);
                                if (!wow64Ret)
                                {
                                    throw new Win32Exception();
                                }

                                if (sourceProcessIsWow64 && !targetProcessIsWow64)
                                {
                                    // Wow64 isn't going to allow this to happen, the best we can do is give a descriptive error to the user.
                                    throw new Win32Exception(Interop.ERROR_PARTIAL_COPY, SR.EnumProcessModuleFailedDueToWow);
                                }
                            }
                            finally
                            {
                                if (hCurProcess != SafeProcessHandle.InvalidHandle)
                                {
                                    hCurProcess.Dispose();
                                }
                            }

                            // If the failure wasn't due to Wow64, try again.
                            for (int i = 0; i < 50; i++)
                            {
                                enumResult = Interop.mincore.EnumProcessModules(processHandle, moduleHandlesArrayHandle.AddrOfPinnedObject(), moduleHandles.Length * IntPtr.Size, ref moduleCount);
                                if (enumResult)
                                {
                                    break;
                                }
                                Thread.Sleep(1);
                            }
                        }
                    }
                    finally
                    {
                        moduleHandlesArrayHandle.Free();
                    }

                    if (!enumResult)
                    {
                        throw new Win32Exception();
                    }

                    moduleCount /= IntPtr.Size;
                    if (moduleCount <= moduleHandles.Length)
                    {
                        break;
                    }
                    moduleHandles = new IntPtr[moduleHandles.Length * 2];
                }
                List <ModuleInfo> moduleInfos = new List <ModuleInfo>();

                int ret;
                for (int i = 0; i < moduleCount; i++)
                {
                    try
                    {
                        ModuleInfo           moduleInfo   = new ModuleInfo();
                        IntPtr               moduleHandle = moduleHandles[i];
                        Interop.NtModuleInfo ntModuleInfo = new Interop.NtModuleInfo();
                        if (!Interop.mincore.GetModuleInformation(processHandle, moduleHandle, ntModuleInfo, Marshal.SizeOf(ntModuleInfo)))
                        {
                            throw new Win32Exception();
                        }
                        moduleInfo._sizeOfImage = ntModuleInfo.SizeOfImage;
                        moduleInfo._entryPoint  = ntModuleInfo.EntryPoint;
                        moduleInfo._baseOfDll   = ntModuleInfo.BaseOfDll;

                        StringBuilder baseName = new StringBuilder(1024);
                        ret = Interop.mincore.GetModuleBaseName(processHandle, moduleHandle, baseName, baseName.Capacity * 2);
                        if (ret == 0)
                        {
                            throw new Win32Exception();
                        }
                        moduleInfo._baseName = baseName.ToString();

                        StringBuilder fileName = new StringBuilder(1024);
                        ret = Interop.mincore.GetModuleFileNameEx(processHandle, moduleHandle, fileName, fileName.Capacity * 2);
                        if (ret == 0)
                        {
                            throw new Win32Exception();
                        }
                        moduleInfo._fileName = fileName.ToString();

                        if (moduleInfo._fileName != null &&
                            moduleInfo._fileName.Length >= 4 &&
                            moduleInfo._fileName.StartsWith(@"\\?\", StringComparison.Ordinal))
                        {
                            moduleInfo._fileName = moduleInfo._fileName.Substring(4);
                        }

                        moduleInfos.Add(moduleInfo);
                    }
                    catch (Win32Exception e)
                    {
                        if (e.NativeErrorCode == Interop.ERROR_INVALID_HANDLE || e.NativeErrorCode == Interop.ERROR_PARTIAL_COPY)
                        {
                            // It's possible that another thread casued this module to become
                            // unloaded (e.g FreeLibrary was called on the module).  Ignore it and
                            // move on.
                        }
                        else
                        {
                            throw;
                        }
                    }

                    //
                    // If the user is only interested in the main module, break now.
                    // This avoid some waste of time. In addition, if the application unloads a DLL
                    // we will not get an exception.
                    //
                    if (firstModuleOnly)
                    {
                        break;
                    }
                }
                ModuleInfo[] temp = new ModuleInfo[moduleInfos.Count];
                moduleInfos.CopyTo(temp, 0);
                return(temp);
            }
            finally
            {
#if FEATURE_TRACESWITCH
                Debug.WriteLineIf(Process._processTracing.TraceVerbose, "Process - CloseHandle(process)");
#endif
                if (!processHandle.IsInvalid)
                {
                    processHandle.Dispose();
                }
            }
        }
Example #25
0
        private static ProcessModuleCollection GetModules(int processId, bool firstModuleOnly)
        {
            // preserving Everett behavior.
            if (processId == SystemProcessID || processId == IdleProcessID)
            {
                // system process and idle process doesn't have any modules
                throw new Win32Exception(Interop.Errors.EFail, SR.EnumProcessModuleFailed);
            }

            SafeProcessHandle processHandle = SafeProcessHandle.InvalidHandle;

            try
            {
                processHandle = ProcessManager.OpenProcess(processId, Interop.Advapi32.ProcessOptions.PROCESS_QUERY_INFORMATION | Interop.Advapi32.ProcessOptions.PROCESS_VM_READ, true);

                IntPtr[] moduleHandles            = new IntPtr[64];
                GCHandle moduleHandlesArrayHandle = new GCHandle();
                int      moduleCount = 0;
                for (;;)
                {
                    bool enumResult = false;
                    try
                    {
                        moduleHandlesArrayHandle = GCHandle.Alloc(moduleHandles, GCHandleType.Pinned);
                        enumResult = Interop.Kernel32.EnumProcessModules(processHandle, moduleHandlesArrayHandle.AddrOfPinnedObject(), moduleHandles.Length * IntPtr.Size, ref moduleCount);

                        // The API we need to use to enumerate process modules differs on two factors:
                        //   1) If our process is running in WOW64.
                        //   2) The bitness of the process we wish to introspect.
                        //
                        // If we are not running in WOW64 or we ARE in WOW64 but want to inspect a 32 bit process
                        // we can call psapi!EnumProcessModules.
                        //
                        // If we are running in WOW64 and we want to inspect the modules of a 64 bit process then
                        // psapi!EnumProcessModules will return false with ERROR_PARTIAL_COPY (299).  In this case we can't
                        // do the enumeration at all.  So we'll detect this case and bail out.
                        //
                        // Also, EnumProcessModules is not a reliable method to get the modules for a process.
                        // If OS loader is touching module information, this method might fail and copy part of the data.
                        // This is no easy solution to this problem. The only reliable way to fix this is to
                        // suspend all the threads in target process. Of course we don't want to do this in Process class.
                        // So we just to try avoid the race by calling the same method 50 (an arbitrary number) times.
                        //
                        if (!enumResult)
                        {
                            bool sourceProcessIsWow64     = false;
                            bool targetProcessIsWow64     = false;
                            SafeProcessHandle hCurProcess = SafeProcessHandle.InvalidHandle;
                            try
                            {
                                hCurProcess = ProcessManager.OpenProcess(unchecked ((int)Interop.Kernel32.GetCurrentProcessId()), Interop.Advapi32.ProcessOptions.PROCESS_QUERY_INFORMATION, true);
                                bool wow64Ret;

                                wow64Ret = Interop.Kernel32.IsWow64Process(hCurProcess, ref sourceProcessIsWow64);
                                if (!wow64Ret)
                                {
                                    throw new Win32Exception();
                                }

                                wow64Ret = Interop.Kernel32.IsWow64Process(processHandle, ref targetProcessIsWow64);
                                if (!wow64Ret)
                                {
                                    throw new Win32Exception();
                                }

                                if (sourceProcessIsWow64 && !targetProcessIsWow64)
                                {
                                    // Wow64 isn't going to allow this to happen, the best we can do is give a descriptive error to the user.
                                    throw new Win32Exception(Interop.Errors.ERROR_PARTIAL_COPY, SR.EnumProcessModuleFailedDueToWow);
                                }
                            }
                            finally
                            {
                                if (hCurProcess != SafeProcessHandle.InvalidHandle)
                                {
                                    hCurProcess.Dispose();
                                }
                            }

                            // If the failure wasn't due to Wow64, try again.
                            for (int i = 0; i < 50; i++)
                            {
                                enumResult = Interop.Kernel32.EnumProcessModules(processHandle, moduleHandlesArrayHandle.AddrOfPinnedObject(), moduleHandles.Length * IntPtr.Size, ref moduleCount);
                                if (enumResult)
                                {
                                    break;
                                }
                                Thread.Sleep(1);
                            }
                        }
                    }
                    finally
                    {
                        moduleHandlesArrayHandle.Free();
                    }

                    if (!enumResult)
                    {
                        throw new Win32Exception();
                    }

                    moduleCount /= IntPtr.Size;
                    if (moduleCount <= moduleHandles.Length)
                    {
                        break;
                    }
                    moduleHandles = new IntPtr[moduleHandles.Length * 2];
                }

                var modules = new ProcessModuleCollection(firstModuleOnly ? 1 : moduleCount);

                char[] chars = new char[1024];

                for (int i = 0; i < moduleCount; i++)
                {
                    if (i > 0)
                    {
                        // If the user is only interested in the main module, break now.
                        // This avoid some waste of time. In addition, if the application unloads a DLL
                        // we will not get an exception.
                        if (firstModuleOnly)
                        {
                            break;
                        }
                    }

                    IntPtr moduleHandle = moduleHandles[i];
                    Interop.Kernel32.NtModuleInfo ntModuleInfo;
                    if (!Interop.Kernel32.GetModuleInformation(processHandle, moduleHandle, out ntModuleInfo))
                    {
                        HandleError();
                        continue;
                    }

                    var module = new ProcessModule()
                    {
                        ModuleMemorySize  = ntModuleInfo.SizeOfImage,
                        EntryPointAddress = ntModuleInfo.EntryPoint,
                        BaseAddress       = ntModuleInfo.BaseOfDll
                    };

                    int length = Interop.Kernel32.GetModuleBaseName(processHandle, moduleHandle, chars, chars.Length);
                    if (length == 0)
                    {
                        HandleError();
                        continue;
                    }

                    module.ModuleName = new string(chars, 0, length);

                    length = Interop.Kernel32.GetModuleFileNameEx(processHandle, moduleHandle, chars, chars.Length);
                    if (length == 0)
                    {
                        HandleError();
                        continue;
                    }

                    module.FileName = (length >= 4 && chars[0] == '\\' && chars[1] == '\\' && chars[2] == '?' && chars[3] == '\\') ?
                                      new string(chars, 4, length - 4) :
                                      new string(chars, 0, length);

                    modules.Add(module);
                }

                return(modules);
            }
            finally
            {
                if (!processHandle.IsInvalid)
                {
                    processHandle.Dispose();
                }
            }
        }
Example #26
0
        /// <summary>Starts the process using the supplied start info.</summary>
        /// <param name="startInfo">The start info with which to start the process.</param>
        private unsafe bool StartWithCreateProcess(ProcessStartInfo startInfo)
        {
            // See knowledge base article Q190351 for an explanation of the following code.  Noteworthy tricky points:
            //    * The handles are duplicated as non-inheritable before they are passed to CreateProcess so
            //      that the child process can not close them
            //    * CreateProcess allows you to redirect all or none of the standard IO handles, so we use
            //      GetStdHandle for the handles that are not being redirected

            var commandLine = new ValueStringBuilder(stackalloc char[256]);

            BuildCommandLine(startInfo, ref commandLine);

            Interop.Kernel32.STARTUPINFO         startupInfo     = default;
            Interop.Kernel32.PROCESS_INFORMATION processInfo     = default;
            Interop.Kernel32.SECURITY_ATTRIBUTES unused_SecAttrs = default;
            SafeProcessHandle procSH = new SafeProcessHandle();

            // handles used in parent process
            SafeFileHandle?parentInputPipeHandle  = null;
            SafeFileHandle?childInputPipeHandle   = null;
            SafeFileHandle?parentOutputPipeHandle = null;
            SafeFileHandle?childOutputPipeHandle  = null;
            SafeFileHandle?parentErrorPipeHandle  = null;
            SafeFileHandle?childErrorPipeHandle   = null;

            // Take a global lock to synchronize all redirect pipe handle creations and CreateProcess
            // calls. We do not want one process to inherit the handles created concurrently for another
            // process, as that will impact the ownership and lifetimes of those handles now inherited
            // into multiple child processes.
            lock (s_createProcessLock)
            {
                try
                {
                    startupInfo.cb = sizeof(Interop.Kernel32.STARTUPINFO);

                    // set up the streams
                    if (startInfo.RedirectStandardInput || startInfo.RedirectStandardOutput || startInfo.RedirectStandardError)
                    {
                        if (startInfo.RedirectStandardInput)
                        {
                            CreatePipe(out parentInputPipeHandle, out childInputPipeHandle, true);
                        }
                        else
                        {
                            childInputPipeHandle = new SafeFileHandle(Interop.Kernel32.GetStdHandle(Interop.Kernel32.HandleTypes.STD_INPUT_HANDLE), false);
                        }

                        if (startInfo.RedirectStandardOutput)
                        {
                            CreatePipe(out parentOutputPipeHandle, out childOutputPipeHandle, false);
                        }
                        else
                        {
                            childOutputPipeHandle = new SafeFileHandle(Interop.Kernel32.GetStdHandle(Interop.Kernel32.HandleTypes.STD_OUTPUT_HANDLE), false);
                        }

                        if (startInfo.RedirectStandardError)
                        {
                            CreatePipe(out parentErrorPipeHandle, out childErrorPipeHandle, false);
                        }
                        else
                        {
                            childErrorPipeHandle = new SafeFileHandle(Interop.Kernel32.GetStdHandle(Interop.Kernel32.HandleTypes.STD_ERROR_HANDLE), false);
                        }

                        startupInfo.hStdInput  = childInputPipeHandle.DangerousGetHandle();
                        startupInfo.hStdOutput = childOutputPipeHandle.DangerousGetHandle();
                        startupInfo.hStdError  = childErrorPipeHandle.DangerousGetHandle();

                        startupInfo.dwFlags = Interop.Advapi32.StartupInfoOptions.STARTF_USESTDHANDLES;
                    }

                    // set up the creation flags parameter
                    int creationFlags = 0;
                    if (startInfo.CreateNoWindow)
                    {
                        creationFlags |= Interop.Advapi32.StartupInfoOptions.CREATE_NO_WINDOW;
                    }

                    // set up the environment block parameter
                    string?environmentBlock = null;
                    if (startInfo._environmentVariables != null)
                    {
                        creationFlags   |= Interop.Advapi32.StartupInfoOptions.CREATE_UNICODE_ENVIRONMENT;
                        environmentBlock = GetEnvironmentVariablesBlock(startInfo._environmentVariables !);
                    }

                    string?workingDirectory = startInfo.WorkingDirectory;
                    if (workingDirectory.Length == 0)
                    {
                        workingDirectory = null;
                    }

                    bool retVal;
                    int  errorCode = 0;

                    if (startInfo.UserName.Length != 0)
                    {
                        if (startInfo.Password != null && startInfo.PasswordInClearText != null)
                        {
                            throw new ArgumentException(SR.CantSetDuplicatePassword);
                        }

                        Interop.Advapi32.LogonFlags logonFlags = (Interop.Advapi32.LogonFlags) 0;
                        if (startInfo.LoadUserProfile)
                        {
                            logonFlags = Interop.Advapi32.LogonFlags.LOGON_WITH_PROFILE;
                        }

                        fixed(char *passwordInClearTextPtr = startInfo.PasswordInClearText ?? string.Empty)
                        fixed(char *environmentBlockPtr = environmentBlock)
                        fixed(char *commandLinePtr      = &commandLine.GetPinnableReference(terminate: true))
                        {
                            IntPtr passwordPtr = (startInfo.Password != null) ?
                                                 Marshal.SecureStringToGlobalAllocUnicode(startInfo.Password) : IntPtr.Zero;

                            try
                            {
                                retVal = Interop.Advapi32.CreateProcessWithLogonW(
                                    startInfo.UserName,
                                    startInfo.Domain,
                                    (passwordPtr != IntPtr.Zero) ? passwordPtr : (IntPtr)passwordInClearTextPtr,
                                    logonFlags,
                                    null,            // we don't need this since all the info is in commandLine
                                    commandLinePtr,
                                    creationFlags,
                                    (IntPtr)environmentBlockPtr,
                                    workingDirectory,
                                    ref startupInfo,        // pointer to STARTUPINFO
                                    ref processInfo         // pointer to PROCESS_INFORMATION
                                    );
                                if (!retVal)
                                {
                                    errorCode = Marshal.GetLastWin32Error();
                                }
                            }
                            finally
                            {
                                if (passwordPtr != IntPtr.Zero)
                                {
                                    Marshal.ZeroFreeGlobalAllocUnicode(passwordPtr);
                                }
                            }
                        }
                    }
                    else
                    {
                        fixed(char *environmentBlockPtr = environmentBlock)
                        fixed(char *commandLinePtr = &commandLine.GetPinnableReference(terminate: true))
                        {
                            retVal = Interop.Kernel32.CreateProcess(
                                null,                        // we don't need this since all the info is in commandLine
                                commandLinePtr,              // pointer to the command line string
                                ref unused_SecAttrs,         // address to process security attributes, we don't need to inherit the handle
                                ref unused_SecAttrs,         // address to thread security attributes.
                                true,                        // handle inheritance flag
                                creationFlags,               // creation flags
                                (IntPtr)environmentBlockPtr, // pointer to new environment block
                                workingDirectory,            // pointer to current directory name
                                ref startupInfo,             // pointer to STARTUPINFO
                                ref processInfo              // pointer to PROCESS_INFORMATION
                                );
                            if (!retVal)
                            {
                                errorCode = Marshal.GetLastWin32Error();
                            }
                        }
                    }

                    if (processInfo.hProcess != IntPtr.Zero && processInfo.hProcess != new IntPtr(-1))
                    {
                        Marshal.InitHandle(procSH, processInfo.hProcess);
                    }
                    if (processInfo.hThread != IntPtr.Zero && processInfo.hThread != new IntPtr(-1))
                    {
                        Interop.Kernel32.CloseHandle(processInfo.hThread);
                    }

                    if (!retVal)
                    {
                        string nativeErrorMessage = errorCode == Interop.Errors.ERROR_BAD_EXE_FORMAT || errorCode == Interop.Errors.ERROR_EXE_MACHINE_TYPE_MISMATCH
                            ? SR.InvalidApplication
                            : GetErrorMessage(errorCode);

                        throw CreateExceptionForErrorStartingProcess(nativeErrorMessage, errorCode, startInfo.FileName, workingDirectory);
                    }
                }
                catch
                {
                    parentInputPipeHandle?.Dispose();
                    parentOutputPipeHandle?.Dispose();
                    parentErrorPipeHandle?.Dispose();
                    procSH.Dispose();
                    throw;
                }
                finally
                {
                    childInputPipeHandle?.Dispose();
                    childOutputPipeHandle?.Dispose();
                    childErrorPipeHandle?.Dispose();
                }
            }

            if (startInfo.RedirectStandardInput)
            {
                Encoding enc = startInfo.StandardInputEncoding ?? GetEncoding((int)Interop.Kernel32.GetConsoleCP());
                _standardInput           = new StreamWriter(new FileStream(parentInputPipeHandle !, FileAccess.Write, 4096, false), enc, 4096);
                _standardInput.AutoFlush = true;
            }
            if (startInfo.RedirectStandardOutput)
            {
                Encoding enc = startInfo.StandardOutputEncoding ?? GetEncoding((int)Interop.Kernel32.GetConsoleOutputCP());
                _standardOutput = new StreamReader(new FileStream(parentOutputPipeHandle !, FileAccess.Read, 4096, false), enc, true, 4096);
            }
            if (startInfo.RedirectStandardError)
            {
                Encoding enc = startInfo.StandardErrorEncoding ?? GetEncoding((int)Interop.Kernel32.GetConsoleOutputCP());
                _standardError = new StreamReader(new FileStream(parentErrorPipeHandle !, FileAccess.Read, 4096, false), enc, true, 4096);
            }

            commandLine.Dispose();

            if (procSH.IsInvalid)
            {
                procSH.Dispose();
                return(false);
            }

            SetProcessHandle(procSH);
            SetProcessId((int)processInfo.dwProcessId);
            return(true);
        }
Example #27
0
 public void Dispose()
 {
     target.Dispose();
     hProcess.Dispose();
 }
    /// <summary>
    /// Calls <see cref="CreateProcessAsUserW"/> and safely stores the obtained handles.
    /// </summary>
    /// <param name="userToken">Token to impersonate the external process</param>
    /// <param name="createFlags">Flags used to create the external process</param>
    /// <param name="startupInfo">Startup information used to create the external process</param>
    /// <returns><c>true</c> if the call to <see cref="CreateProcessAsUserW"/> was successful; otherwise <c>false</c></returns>
    private bool SafeCreateProcessAsUserW(IntPtr userToken, CreateProcessFlags createFlags, StartupInfo startupInfo)
    {
      _processHandle = new SafeProcessHandle();
      var threadHandle = new SafeThreadHandle();
      bool success;

      // The following is necessary to make sure that processInformation.hProcess and processInformation.hThread
      // are safely stored in the respective SafeHandle classes. It is, unfortunately, not possible to define
      // processInformation.hProcess and processInformation.hThread as SafeHandles and use processInformation
      // as an out parameter, because the unmanaged code is not able to create these objects. We therefore use
      // IntPtr and ensure in the following that the IntPtrs are stored in SafeHandle objects immediately after
      // they have been obtained.
      // For details see here: https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.runtimehelpers.prepareconstrainedregions(v=vs.110).aspx
      RuntimeHelpers.PrepareConstrainedRegions();
      try { }
      finally
      {
        ProcessInformation processInformation;
        success = CreateProcessAsUserW(userToken, null, GetCommandLine(), IntPtr.Zero, IntPtr.Zero, true, createFlags, IntPtr.Zero, null, startupInfo, out processInformation);
        if (success)
        {
          _processHandle.InitialSetHandle(processInformation.hProcess);
          threadHandle.InitialSetHandle(processInformation.hThread);
          _processId = processInformation.dwProcessId;
        }
      }
      
      // We don't need the threadHandle and therefore immediately dispose it.
      threadHandle.Dispose();

      if (success)
        return true;

      _processHandle.Dispose();
      var error = Marshal.GetLastWin32Error();
      _debugLogger.Error("AsyncImpersonationProcess ({0}): Cannot start process. ErrorCode: {1} ({2})", StartInfo.FileName, error, new Win32Exception(error).Message);
      return false;
    }
        [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported)), PlatformSpecific(TestPlatforms.Windows), OuterLoop]         // Uses P/Invokes, Requires admin privileges
        public void TestUserCredentialsPropertiesOnWindows()
        {
            // [SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Unit test dummy credentials.")]
            string username = "******", password = "******";

            try
            {
                Interop.NetUserAdd(username, password);
            }
            catch (Exception exc)
            {
                Console.Error.WriteLine("TestUserCredentialsPropertiesOnWindows: NetUserAdd failed: {0}", exc.Message);
                return; // test is irrelevant if we can't add a user
            }

            bool hasStarted          = false;
            SafeProcessHandle handle = null;
            Process           p      = null;

            try
            {
                p = CreateProcessLong();

                p.StartInfo.LoadUserProfile     = true;
                p.StartInfo.UserName            = username;
                p.StartInfo.PasswordInClearText = password;

                hasStarted = p.Start();

                if (Interop.OpenProcessToken(p.SafeHandle, 0x8u, out handle))
                {
                    SecurityIdentifier sid;
                    if (Interop.ProcessTokenToSid(handle, out sid))
                    {
                        string actualUserName = sid.Translate(typeof(NTAccount)).ToString();
                        int    indexOfDomain  = actualUserName.IndexOf('\\');
                        if (indexOfDomain != -1)
                        {
                            actualUserName = actualUserName.Substring(indexOfDomain + 1);
                        }

                        bool isProfileLoaded = GetNamesOfUserProfiles().Any(profile => profile.Equals(username));

                        Assert.Equal(username, actualUserName);
                        Assert.True(isProfileLoaded);
                    }
                }
            }
            finally
            {
                IEnumerable <uint> collection = new uint[] { 0 /* NERR_Success */, 2221 /* NERR_UserNotFound */ };
                Assert.Contains <uint>(Interop.NetUserDel(null, username), collection);

                if (handle != null)
                {
                    handle.Dispose();
                }

                if (hasStarted)
                {
                    p.Kill();

                    Assert.True(p.WaitForExit(WaitInMS));
                }
            }
        }
Example #30
0
 public void Dispose()
 {
     processHandle?.Dispose();
     tokenSource.Dispose();
     GC.SuppressFinalize(this);
 }
Example #31
0
 public void Dispose()
 {
     _processHandle.Dispose();
 }