예제 #1
0
        private static MemoryNode Root()
        {
            var ret = new MemoryNode();

            ret.info.RegionSize = unchecked (new IntPtr((long)ulong.MaxValue));
            ret.Name            = "[ROOT]";
            return(ret);
        }
예제 #2
0
        private void Insert(MemoryNode newNode)
        {
            Debug.Assert(Address <= newNode.Address && newNode.End <= End);
            if (Children == null)
            {
                Children = new List <MemoryNode>();
            }

            // Search backwards for efficiency.
            for (int i = Children.Count; 0 < i;)
            {
                var child = Children[--i];
                if (child.Address <= newNode.Address && newNode.End <= child.End)
                {
                    child.Insert(newNode);
                    return;
                }
            }
            Children.Add(newNode);
            newNode.Parent = this;
        }
예제 #3
0
        /// <summary>
        /// This is the main entry point into the MemoryNode class.  Basically giving a process ID return
        /// a MemoryNode that represents the roll-up of all memory in the process.
        /// </summary>
        public unsafe static MemoryNode MemorySnapShotForProcess(int processID)
        {
            var root    = Root();
            var process = Process.GetProcessById(processID);

            bool is32BitProcess = false;

            NativeMethods.IsWow64Process(process.Handle, out is32BitProcess);
            var kernelToUser = new KernelToUserDriveMapping();

            var  name       = new StringBuilder(260);
            long MaxAddress = 0x7fffffff;
            long address    = 0;

            do
            {
                var child = new MemoryNode();

                int result = NativeMethods.VirtualQueryEx(process.Handle,
                                                          (IntPtr)address,
                                                          out child.info, (uint)Marshal.SizeOf(child.info));
                address = (long)child.info.BaseAddress + (long)child.info.RegionSize;

                // TODO FIX NOW worry about error codes.
                if (result == 0)
                {
                    break;
                }

                if (child.info.Type == NativeMethods.MemoryType.MEM_IMAGE || child.info.Type == NativeMethods.MemoryType.MEM_MAPPED)
                {
                    name.Clear();
                    var ret = NativeMethods.GetMappedFileName(process.Handle, (IntPtr)address, name, name.Capacity);
                    if (ret != 0)
                    {
                        var kernelName = name.ToString();
                        child.Name = kernelToUser[kernelName];
                    }
                    else
                    {
                        Debug.WriteLine("Error, GetMappedFileName failed.");
                    }
                }
                root.Insert(child);
            } while (address <= MaxAddress);

            NativeMethods.PSAPI_WORKING_SET_INFORMATION *WSInfo = stackalloc NativeMethods.PSAPI_WORKING_SET_INFORMATION[1];
            NativeMethods.QueryWorkingSet(process.Handle, WSInfo, sizeof(NativeMethods.PSAPI_WORKING_SET_INFORMATION));
            int buffSize = (int)(WSInfo->NumberOfEntries) * 8 + 8 + 1024; // The 1024 is to allow for working set growth

            WSInfo = (NativeMethods.PSAPI_WORKING_SET_INFORMATION *)Marshal.AllocHGlobal(buffSize);
            if (!NativeMethods.QueryWorkingSet(process.Handle, WSInfo, buffSize))
            {
                Marshal.FreeHGlobal((IntPtr)WSInfo);
                Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());
            }

            // Copy the working set info to an array and sort the page addresses.
            int numBlocks = (int)WSInfo->NumberOfEntries;

            ulong[] blocks = new ulong[numBlocks];
            for (var curWSIdx = 0; curWSIdx < numBlocks; curWSIdx++)
            {
                blocks[curWSIdx] = WSInfo->WorkingSetInfo(curWSIdx).Address;
            }
            Array.Sort(blocks);
            Marshal.FreeHGlobal((IntPtr)WSInfo);

            // Attribute the working set to the regions of memory
            int curPageIdx = 0;

            foreach (var region in root.Children)
            {
                var end = region.End;
                while (curPageIdx < blocks.Length && blocks[curPageIdx] < end)
                {
                    curPageIdx++;
                    region.PrivateWorkingSet += 4; // TODO FIX NOW
                }
            }

            GC.KeepAlive(process);
            return(root);
        }