Esempio n. 1
0
        /*
         *  -----------------------
         *  Memory Buffer Factories
         *  -----------------------
         */

        /// <summary>
        /// Finds an appropriate location where a <see cref="MemoryBuffer"/>;
        /// or other memory allocation could be performed.
        /// Note: Please see remarks for this function.
        /// </summary>
        /// <param name = "size" > The space in bytes that the specific <see cref="MemoryBuffer"/> would require to accomodate.</param>
        /// <param name="minimumAddress">The minimum absolute address to find a buffer in.</param>
        /// <param name="maximumAddress">The maximum absolute address to find a buffer in.</param>
        /// <param name="isPrivateBuffer">Defines whether the buffer type created is a shared or private buffer.</param>
        /// <remarks>
        /// WARNING:
        ///     Using this in a multithreaded environment can be dangerous, be careful.
        ///     It is possible to have a race condition on memory allocation.
        ///     If you want to just allocate memory, please use the provided <see cref="Allocate"/> function instead.
        /// </remarks>
        public BufferAllocationProperties FindBufferLocation(int size, long minimumAddress, long maximumAddress, bool isPrivateBuffer = false)
        {
            if (minimumAddress <= 0)
            {
                throw new ArgumentException("Please do not set the minimum address to 0 or negative. It collides with the return values of Windows API functions" +
                                            "where e.g. 0 is returned on failure but you can also allocate successfully on 0.");
            }

            int bufferSize = GetBufferSize(size, isPrivateBuffer);

            // Search through the buffer cache first.
            if (_pageCache != null)
            {
                for (int x = 0; x < _pageCache.Length; x++)
                {
                    var pointer = GetBufferPointerInPageRange(ref _pageCache[x], bufferSize, (IntPtr)minimumAddress, (IntPtr)maximumAddress);
                    if (pointer != IntPtr.Zero)
                    {
                        // Page cache contains a page that can "work". Check if this page is still valid by running VirtualQuery on it
                        // and rechecking the new page.
                        var memoryBasicInformation = new MEMORY_BASIC_INFORMATION();
                        var result = _virtualQueryFunction(Process.Handle, pointer, ref memoryBasicInformation);
                        if (result == (UIntPtr)0)
                        {
                            throw new Exception("VirtualQuery failed. Result is 0.");
                        }

                        var newPointer = GetBufferPointerInPageRange(ref memoryBasicInformation, bufferSize, (IntPtr)minimumAddress, (IntPtr)maximumAddress);
                        if (newPointer != IntPtr.Zero)
                        {
                            return(new BufferAllocationProperties(newPointer, bufferSize));
                        }
                    }
                }
            }

            // Not found in cache, get all real pages and try find appropriate spot.
            var memoryPages = MemoryPages.GetPages(Process).ToArray();

            _pageCache = memoryPages;

            for (int x = 0; x < memoryPages.Length; x++)
            {
                var pointer = GetBufferPointerInPageRange(ref memoryPages[x], bufferSize, (IntPtr)minimumAddress, (IntPtr)maximumAddress);
                if (pointer != IntPtr.Zero)
                {
                    return(new BufferAllocationProperties(pointer, bufferSize));
                }
            }

            throw new Exception($"Unable to find memory location to fit MemoryBuffer of size {size} ({bufferSize}) between {minimumAddress.ToString("X")} and {maximumAddress.ToString("X")}.");
        }
        /*
         *  -----------------------
         *  Memory Buffer Factories
         *  -----------------------
         */

        /// <summary>
        /// Finds an appropriate location where a <see cref="MemoryBuffer"/>;
        /// or other memory allocation could be performed.
        /// Note: Please see remarks for this function.
        /// </summary>
        /// <param name = "size" > The space in bytes that the specific <see cref="MemoryBuffer"/> would require to accomodate.</param>
        /// <param name="minimumAddress">The minimum absolute address to find a buffer in.</param>
        /// <param name="maximumAddress">The maximum absolute address to find a buffer in.</param>
        /// <param name="isPrivateBuffer">Defines whether the buffer type created is a shared or private buffer.</param>
        /// <remarks>
        /// WARNING:
        ///     Using this in a multithreaded environment can be dangerous, be careful.
        ///     It is possible to have a race condition on memory allocation.
        ///     If you want to just allocate memory, please use the provided <see cref="Allocate"/> function instead.
        /// </remarks>
        public BufferAllocationProperties FindBufferLocation(int size, nuint minimumAddress, nuint maximumAddress, bool isPrivateBuffer = false)
        {
            if (minimumAddress <= 0)
            {
                throw new ArgumentException("Please do not set the minimum address to 0 or negative. It collides with the return values of Windows API functions" +
                                            "where e.g. 0 is returned on failure but you can also allocate successfully on 0.");
            }

            int bufferSize = GetBufferSize(size, isPrivateBuffer);

            // Not found in cache, get all real pages and try find appropriate spot.
            var memoryPages = MemoryPages.GetPages(Process);

            for (int x = 0; x < memoryPages.Count; x++)
            {
                var pointer = GetBufferPointerInPageRange(memoryPages[x], bufferSize, minimumAddress, maximumAddress);
                if (pointer != 0)
                {
                    return(new BufferAllocationProperties(pointer, bufferSize));
                }
            }

            throw new Exception($"Unable to find memory location to fit MemoryBuffer of size {size} ({bufferSize}) between {minimumAddress} and {maximumAddress}.");
        }