예제 #1
0
        private static Dictionary <uint, ReportedProcess> GetSurvivingChildProcesses(JobObject jobObject)
        {
            if (!jobObject.TryGetProcessIds(out uint[] survivingChildProcessIds) || survivingChildProcessIds.Length == 0)
            {
                return(null);
            }

            var survivingChildProcesses = new Dictionary <uint, ReportedProcess>();

            foreach (uint processId in survivingChildProcessIds)
            {
                using (SafeProcessHandle processHandle = ProcessUtilities.OpenProcess(
                           ProcessSecurityAndAccessRights.PROCESS_QUERY_INFORMATION |
                           ProcessSecurityAndAccessRights.PROCESS_VM_READ,
                           false,
                           processId))
                {
                    if (processHandle.IsInvalid)
                    {
                        // we are too late: could not open process
                        continue;
                    }

                    if (!jobObject.ContainsProcess(processHandle))
                    {
                        // we are too late: process id got reused by another process
                        continue;
                    }

                    int exitCode;
                    if (!ProcessUtilities.GetExitCodeProcess(processHandle, out exitCode))
                    {
                        // we are too late: process id got reused by another process
                        continue;
                    }

                    using (PooledObjectWrapper <StringBuilder> wrap = Pools.GetStringBuilder())
                    {
                        StringBuilder sb = wrap.Instance;
                        if (sb.Capacity < MaxProcessPathLength)
                        {
                            sb.Capacity = MaxProcessPathLength;
                        }

                        if (ProcessUtilities.GetModuleFileNameEx(processHandle, IntPtr.Zero, sb, (uint)sb.Capacity) <= 0)
                        {
                            // we are probably too late
                            continue;
                        }

                        // Attempt to read the process arguments (command line) from the process
                        // memory. This is not fatal if it does not succeed.
                        string processArgs = string.Empty;

                        var  basicInfoSize = (uint)Marshal.SizeOf <Native.Processes.Windows.ProcessUtilitiesWin.PROCESS_BASIC_INFORMATION>();
                        var  basicInfoPtr  = Marshal.AllocHGlobal((int)basicInfoSize);
                        uint basicInfoReadLen;
                        try
                        {
                            if (Native.Processes.Windows.ProcessUtilitiesWin.NtQueryInformationProcess(
                                    processHandle,
                                    Native.Processes.Windows.ProcessUtilitiesWin.ProcessInformationClass.ProcessBasicInformation,
                                    basicInfoPtr, basicInfoSize, out basicInfoReadLen) == 0)
                            {
                                Native.Processes.Windows.ProcessUtilitiesWin.PROCESS_BASIC_INFORMATION basicInformation = Marshal.PtrToStructure <Native.Processes.Windows.ProcessUtilitiesWin.PROCESS_BASIC_INFORMATION>(basicInfoPtr);
                                Contract.Assert(basicInformation.UniqueProcessId == processId);

                                // NativeMethods.ReadProcessStructure and NativeMethods.ReadUnicodeString handle null\zero addresses
                                // passed into them. Since these are all value types, then there is no need to do any type
                                // of checking as passing zero through will just result in an empty process args string.
                                var peb = Native.Processes.Windows.ProcessUtilitiesWin.ReadProcessStructure <Native.Processes.Windows.ProcessUtilitiesWin.PEB>(processHandle, basicInformation.PebBaseAddress);
                                var processParameters = Native.Processes.Windows.ProcessUtilitiesWin.ReadProcessStructure <Native.Processes.Windows.ProcessUtilitiesWin.RTL_USER_PROCESS_PARAMETERS>(processHandle, peb.ProcessParameters);
                                processArgs = Native.Processes.Windows.ProcessUtilitiesWin.ReadProcessUnicodeString(processHandle, processParameters.CommandLine);
                            }
                        }
                        finally
                        {
                            Marshal.FreeHGlobal(basicInfoPtr);
                        }

                        string path = sb.ToString();
                        survivingChildProcesses.Add(processId, new ReportedProcess(processId, path, processArgs));
                    }
                }
            }


            return(survivingChildProcesses);
        }