diff options
| author | TSR Berry <20988865+TSRBerry@users.noreply.github.com> | 2023-04-08 01:22:00 +0200 |
|---|---|---|
| committer | Mary <thog@protonmail.com> | 2023-04-27 23:51:14 +0200 |
| commit | cee712105850ac3385cd0091a923438167433f9f (patch) | |
| tree | 4a5274b21d8b7f938c0d0ce18736d3f2993b11b1 /Ryujinx.Memory/WindowsShared | |
| parent | cd124bda587ef09668a971fa1cac1c3f0cfc9f21 (diff) | |
Move solution and projects to src
Diffstat (limited to 'Ryujinx.Memory/WindowsShared')
| -rw-r--r-- | Ryujinx.Memory/WindowsShared/MappingTree.cs | 87 | ||||
| -rw-r--r-- | Ryujinx.Memory/WindowsShared/PlaceholderManager.cs | 736 | ||||
| -rw-r--r-- | Ryujinx.Memory/WindowsShared/WindowsApi.cs | 101 | ||||
| -rw-r--r-- | Ryujinx.Memory/WindowsShared/WindowsApiException.cs | 24 | ||||
| -rw-r--r-- | Ryujinx.Memory/WindowsShared/WindowsFlags.cs | 52 |
5 files changed, 0 insertions, 1000 deletions
diff --git a/Ryujinx.Memory/WindowsShared/MappingTree.cs b/Ryujinx.Memory/WindowsShared/MappingTree.cs deleted file mode 100644 index 97758c2b..00000000 --- a/Ryujinx.Memory/WindowsShared/MappingTree.cs +++ /dev/null @@ -1,87 +0,0 @@ -using Ryujinx.Common.Collections; -using System; - -namespace Ryujinx.Memory.WindowsShared -{ - /// <summary> - /// A intrusive Red-Black Tree that also supports getting nodes overlapping a given range. - /// </summary> - /// <typeparam name="T">Type of the value stored on the node</typeparam> - class MappingTree<T> : IntrusiveRedBlackTree<RangeNode<T>> - { - private const int ArrayGrowthSize = 16; - - public int GetNodes(ulong start, ulong end, ref RangeNode<T>[] overlaps, int overlapCount = 0) - { - RangeNode<T> node = this.GetNodeByKey(start); - - for (; node != null; node = node.Successor) - { - if (overlaps.Length <= overlapCount) - { - Array.Resize(ref overlaps, overlapCount + ArrayGrowthSize); - } - - overlaps[overlapCount++] = node; - - if (node.End >= end) - { - break; - } - } - - return overlapCount; - } - } - - class RangeNode<T> : IntrusiveRedBlackTreeNode<RangeNode<T>>, IComparable<RangeNode<T>>, IComparable<ulong> - { - public ulong Start { get; } - public ulong End { get; private set; } - public T Value { get; } - - public RangeNode(ulong start, ulong end, T value) - { - Start = start; - End = end; - Value = value; - } - - public void Extend(ulong sizeDelta) - { - End += sizeDelta; - } - - public int CompareTo(RangeNode<T> other) - { - if (Start < other.Start) - { - return -1; - } - else if (Start <= other.End - 1UL) - { - return 0; - } - else - { - return 1; - } - } - - public int CompareTo(ulong address) - { - if (address < Start) - { - return 1; - } - else if (address <= End - 1UL) - { - return 0; - } - else - { - return -1; - } - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Memory/WindowsShared/PlaceholderManager.cs b/Ryujinx.Memory/WindowsShared/PlaceholderManager.cs deleted file mode 100644 index 3022b661..00000000 --- a/Ryujinx.Memory/WindowsShared/PlaceholderManager.cs +++ /dev/null @@ -1,736 +0,0 @@ -using Ryujinx.Common.Collections; -using Ryujinx.Common.Memory.PartialUnmaps; -using System; -using System.Diagnostics; -using System.Runtime.CompilerServices; -using System.Runtime.Versioning; -using System.Threading; - -namespace Ryujinx.Memory.WindowsShared -{ - /// <summary> - /// Windows memory placeholder manager. - /// </summary> - [SupportedOSPlatform("windows")] - class PlaceholderManager - { - private const int InitialOverlapsSize = 10; - - private readonly MappingTree<ulong> _mappings; - private readonly MappingTree<MemoryPermission> _protections; - private readonly IntPtr _partialUnmapStatePtr; - private readonly Thread _partialUnmapTrimThread; - - /// <summary> - /// Creates a new instance of the Windows memory placeholder manager. - /// </summary> - public PlaceholderManager() - { - _mappings = new MappingTree<ulong>(); - _protections = new MappingTree<MemoryPermission>(); - - _partialUnmapStatePtr = PartialUnmapState.GlobalState; - - _partialUnmapTrimThread = new Thread(TrimThreadLocalMapLoop); - _partialUnmapTrimThread.Name = "CPU.PartialUnmapTrimThread"; - _partialUnmapTrimThread.IsBackground = true; - _partialUnmapTrimThread.Start(); - } - - /// <summary> - /// Gets a reference to the partial unmap state struct. - /// </summary> - /// <returns>A reference to the partial unmap state struct</returns> - private unsafe ref PartialUnmapState GetPartialUnmapState() - { - return ref Unsafe.AsRef<PartialUnmapState>((void*)_partialUnmapStatePtr); - } - - /// <summary> - /// Trims inactive threads from the partial unmap state's thread mapping every few seconds. - /// Should be run in a Background thread so that it doesn't stop the program from closing. - /// </summary> - private void TrimThreadLocalMapLoop() - { - while (true) - { - Thread.Sleep(2000); - GetPartialUnmapState().TrimThreads(); - } - } - - /// <summary> - /// Reserves a range of the address space to be later mapped as shared memory views. - /// </summary> - /// <param name="address">Start address of the region to reserve</param> - /// <param name="size">Size in bytes of the region to reserve</param> - public void ReserveRange(ulong address, ulong size) - { - lock (_mappings) - { - _mappings.Add(new RangeNode<ulong>(address, address + size, ulong.MaxValue)); - } - - lock (_protections) - { - _protections.Add(new RangeNode<MemoryPermission>(address, address + size, MemoryPermission.None)); - } - } - - /// <summary> - /// Unreserves a range of memory that has been previously reserved with <see cref="ReserveRange"/>. - /// </summary> - /// <param name="address">Start address of the region to unreserve</param> - /// <param name="size">Size in bytes of the region to unreserve</param> - /// <exception cref="WindowsApiException">Thrown when the Windows API returns an error unreserving the memory</exception> - public void UnreserveRange(ulong address, ulong size) - { - ulong endAddress = address + size; - - lock (_mappings) - { - RangeNode<ulong> node = _mappings.GetNodeByKey(address); - RangeNode<ulong> successorNode; - - for (; node != null; node = successorNode) - { - successorNode = node.Successor; - - if (IsMapped(node.Value)) - { - if (!WindowsApi.UnmapViewOfFile2(WindowsApi.CurrentProcessHandle, (IntPtr)node.Start, 2)) - { - throw new WindowsApiException("UnmapViewOfFile2"); - } - } - - _mappings.Remove(node); - - if (node.End >= endAddress) - { - break; - } - } - } - - RemoveProtection(address, size); - } - - /// <summary> - /// Maps a shared memory view on a previously reserved memory region. - /// </summary> - /// <param name="sharedMemory">Shared memory that will be the backing storage for the view</param> - /// <param name="srcOffset">Offset in the shared memory to map</param> - /// <param name="location">Address to map the view into</param> - /// <param name="size">Size of the view in bytes</param> - /// <param name="owner">Memory block that owns the mapping</param> - public void MapView(IntPtr sharedMemory, ulong srcOffset, IntPtr location, IntPtr size, MemoryBlock owner) - { - ref var partialUnmapLock = ref GetPartialUnmapState().PartialUnmapLock; - partialUnmapLock.AcquireReaderLock(); - - try - { - UnmapViewInternal(sharedMemory, location, size, owner, updateProtection: false); - MapViewInternal(sharedMemory, srcOffset, location, size, updateProtection: true); - } - finally - { - partialUnmapLock.ReleaseReaderLock(); - } - } - - /// <summary> - /// Maps a shared memory view on a previously reserved memory region. - /// </summary> - /// <param name="sharedMemory">Shared memory that will be the backing storage for the view</param> - /// <param name="srcOffset">Offset in the shared memory to map</param> - /// <param name="location">Address to map the view into</param> - /// <param name="size">Size of the view in bytes</param> - /// <param name="updateProtection">Indicates if the memory protections should be updated after the map</param> - /// <exception cref="WindowsApiException">Thrown when the Windows API returns an error mapping the memory</exception> - private void MapViewInternal(IntPtr sharedMemory, ulong srcOffset, IntPtr location, IntPtr size, bool updateProtection) - { - SplitForMap((ulong)location, (ulong)size, srcOffset); - - var ptr = WindowsApi.MapViewOfFile3( - sharedMemory, - WindowsApi.CurrentProcessHandle, - location, - srcOffset, - size, - 0x4000, - MemoryProtection.ReadWrite, - IntPtr.Zero, - 0); - - if (ptr == IntPtr.Zero) - { - throw new WindowsApiException("MapViewOfFile3"); - } - - if (updateProtection) - { - UpdateProtection((ulong)location, (ulong)size, MemoryPermission.ReadAndWrite); - } - } - - /// <summary> - /// Splits a larger placeholder, slicing at the start and end address, for a new memory mapping. - /// </summary> - /// <param name="address">Address to split</param> - /// <param name="size">Size of the new region</param> - /// <param name="backingOffset">Offset in the shared memory that will be mapped</param> - private void SplitForMap(ulong address, ulong size, ulong backingOffset) - { - ulong endAddress = address + size; - - var overlaps = new RangeNode<ulong>[InitialOverlapsSize]; - - lock (_mappings) - { - int count = _mappings.GetNodes(address, endAddress, ref overlaps); - - Debug.Assert(count == 1); - Debug.Assert(!IsMapped(overlaps[0].Value)); - - var overlap = overlaps[0]; - - ulong overlapStart = overlap.Start; - ulong overlapEnd = overlap.End; - ulong overlapValue = overlap.Value; - - _mappings.Remove(overlap); - - bool overlapStartsBefore = overlapStart < address; - bool overlapEndsAfter = overlapEnd > endAddress; - - if (overlapStartsBefore && overlapEndsAfter) - { - CheckFreeResult(WindowsApi.VirtualFree( - (IntPtr)address, - (IntPtr)size, - AllocationType.Release | AllocationType.PreservePlaceholder)); - - _mappings.Add(new RangeNode<ulong>(overlapStart, address, overlapValue)); - _mappings.Add(new RangeNode<ulong>(endAddress, overlapEnd, AddBackingOffset(overlapValue, endAddress - overlapStart))); - } - else if (overlapStartsBefore) - { - ulong overlappedSize = overlapEnd - address; - - CheckFreeResult(WindowsApi.VirtualFree( - (IntPtr)address, - (IntPtr)overlappedSize, - AllocationType.Release | AllocationType.PreservePlaceholder)); - - _mappings.Add(new RangeNode<ulong>(overlapStart, address, overlapValue)); - } - else if (overlapEndsAfter) - { - ulong overlappedSize = endAddress - overlapStart; - - CheckFreeResult(WindowsApi.VirtualFree( - (IntPtr)overlapStart, - (IntPtr)overlappedSize, - AllocationType.Release | AllocationType.PreservePlaceholder)); - - _mappings.Add(new RangeNode<ulong>(endAddress, overlapEnd, AddBackingOffset(overlapValue, overlappedSize))); - } - - _mappings.Add(new RangeNode<ulong>(address, endAddress, backingOffset)); - } - } - - /// <summary> - /// Unmaps a view that has been previously mapped with <see cref="MapView"/>. - /// </summary> - /// <remarks> - /// For "partial unmaps" (when not the entire mapped range is being unmapped), it might be - /// necessary to unmap the whole range and then remap the sub-ranges that should remain mapped. - /// </remarks> - /// <param name="sharedMemory">Shared memory that the view being unmapped belongs to</param> - /// <param name="location">Address to unmap</param> - /// <param name="size">Size of the region to unmap in bytes</param> - /// <param name="owner">Memory block that owns the mapping</param> - public void UnmapView(IntPtr sharedMemory, IntPtr location, IntPtr size, MemoryBlock owner) - { - ref var partialUnmapLock = ref GetPartialUnmapState().PartialUnmapLock; - partialUnmapLock.AcquireReaderLock(); - - try - { - UnmapViewInternal(sharedMemory, location, size, owner, updateProtection: true); - } - finally - { - partialUnmapLock.ReleaseReaderLock(); - } - } - - /// <summary> - /// Unmaps a view that has been previously mapped with <see cref="MapView"/>. - /// </summary> - /// <remarks> - /// For "partial unmaps" (when not the entire mapped range is being unmapped), it might be - /// necessary to unmap the whole range and then remap the sub-ranges that should remain mapped. - /// </remarks> - /// <param name="sharedMemory">Shared memory that the view being unmapped belongs to</param> - /// <param name="location">Address to unmap</param> - /// <param name="size">Size of the region to unmap in bytes</param> - /// <param name="owner">Memory block that owns the mapping</param> - /// <param name="updateProtection">Indicates if the memory protections should be updated after the unmap</param> - /// <exception cref="WindowsApiException">Thrown when the Windows API returns an error unmapping or remapping the memory</exception> - private void UnmapViewInternal(IntPtr sharedMemory, IntPtr location, IntPtr size, MemoryBlock owner, bool updateProtection) - { - ulong startAddress = (ulong)location; - ulong unmapSize = (ulong)size; - ulong endAddress = startAddress + unmapSize; - - var overlaps = new RangeNode<ulong>[InitialOverlapsSize]; - int count; - - lock (_mappings) - { - count = _mappings.GetNodes(startAddress, endAddress, ref overlaps); - } - - for (int index = 0; index < count; index++) - { - var overlap = overlaps[index]; - - if (IsMapped(overlap.Value)) - { - lock (_mappings) - { - _mappings.Remove(overlap); - _mappings.Add(new RangeNode<ulong>(overlap.Start, overlap.End, ulong.MaxValue)); - } - - bool overlapStartsBefore = overlap.Start < startAddress; - bool overlapEndsAfter = overlap.End > endAddress; - - if (overlapStartsBefore || overlapEndsAfter) - { - // If the overlap extends beyond the region we are unmapping, - // then we need to re-map the regions that are supposed to remain mapped. - // This is necessary because Windows does not support partial view unmaps. - // That is, you can only fully unmap a view that was previously mapped, you can't just unmap a chunck of it. - - ref var partialUnmapState = ref GetPartialUnmapState(); - ref var partialUnmapLock = ref partialUnmapState.PartialUnmapLock; - partialUnmapLock.UpgradeToWriterLock(); - - try - { - partialUnmapState.PartialUnmapsCount++; - - if (!WindowsApi.UnmapViewOfFile2(WindowsApi.CurrentProcessHandle, (IntPtr)overlap.Start, 2)) - { - throw new WindowsApiException("UnmapViewOfFile2"); - } - - if (overlapStartsBefore) - { - ulong remapSize = startAddress - overlap.Start; - - MapViewInternal(sharedMemory, overlap.Value, (IntPtr)overlap.Start, (IntPtr)remapSize, updateProtection: false); - RestoreRangeProtection(overlap.Start, remapSize); - } - - if (overlapEndsAfter) - { - ulong overlappedSize = endAddress - overlap.Start; - ulong remapBackingOffset = overlap.Value + overlappedSize; - ulong remapAddress = overlap.Start + overlappedSize; - ulong remapSize = overlap.End - endAddress; - - MapViewInternal(sharedMemory, remapBackingOffset, (IntPtr)remapAddress, (IntPtr)remapSize, updateProtection: false); - RestoreRangeProtection(remapAddress, remapSize); - } - } - finally - { - partialUnmapLock.DowngradeFromWriterLock(); - } - } - else if (!WindowsApi.UnmapViewOfFile2(WindowsApi.CurrentProcessHandle, (IntPtr)overlap.Start, 2)) - { - throw new WindowsApiException("UnmapViewOfFile2"); - } - } - } - - CoalesceForUnmap(startAddress, unmapSize, owner); - - if (updateProtection) - { - UpdateProtection(startAddress, unmapSize, MemoryPermission.None); - } - } - - /// <summary> - /// Coalesces adjacent placeholders after unmap. - /// </summary> - /// <param name="address">Address of the region that was unmapped</param> - /// <param name="size">Size of the region that was unmapped in bytes</param> - /// <param name="owner">Memory block that owns the mapping</param> - private void CoalesceForUnmap(ulong address, ulong size, MemoryBlock owner) - { - ulong endAddress = address + size; - ulong blockAddress = (ulong)owner.Pointer; - ulong blockEnd = blockAddress + owner.Size; - int unmappedCount = 0; - - lock (_mappings) - { - RangeNode<ulong> node = _mappings.GetNodeByKey(address); - - if (node == null) - { - // Nothing to coalesce if we have no overlaps. - return; - } - - RangeNode<ulong> predecessor = node.Predecessor; - RangeNode<ulong> successor = null; - - for (; node != null; node = successor) - { - successor = node.Successor; - var overlap = node; - - if (!IsMapped(overlap.Value)) - { - address = Math.Min(address, overlap.Start); - endAddress = Math.Max(endAddress, overlap.End); - - _mappings.Remove(overlap); - unmappedCount++; - } - - if (node.End >= endAddress) - { - break; - } - } - - if (predecessor != null && !IsMapped(predecessor.Value) && predecessor.Start >= blockAddress) - { - address = Math.Min(address, predecessor.Start); - - _mappings.Remove(predecessor); - unmappedCount++; - } - - if (successor != null && !IsMapped(successor.Value) && successor.End <= blockEnd) - { - endAddress = Math.Max(endAddress, successor.End); - - _mappings.Remove(successor); - unmappedCount++; - } - - _mappings.Add(new RangeNode<ulong>(address, endAddress, ulong.MaxValue)); - } - - if (unmappedCount > 1) - { - size = endAddress - address; - - CheckFreeResult(WindowsApi.VirtualFree( - (IntPtr)address, - (IntPtr)size, - AllocationType.Release | AllocationType.CoalescePlaceholders)); - } - } - - /// <summary> - /// Reprotects a region of memory that has been mapped. - /// </summary> - /// <param name="address">Address of the region to reprotect</param> - /// <param name="size">Size of the region to reprotect in bytes</param> - /// <param name="permission">New permissions</param> - /// <returns>True if the reprotection was successful, false otherwise</returns> - public bool ReprotectView(IntPtr address, IntPtr size, MemoryPermission permission) - { - ref var partialUnmapLock = ref GetPartialUnmapState().PartialUnmapLock; - partialUnmapLock.AcquireReaderLock(); - - try - { - return ReprotectViewInternal(address, size, permission, false); - } - finally - { - partialUnmapLock.ReleaseReaderLock(); - } - } - - /// <summary> - /// Reprotects a region of memory that has been mapped. - /// </summary> - /// <param name="address">Address of the region to reprotect</param> - /// <param name="size">Size of the region to reprotect in bytes</param> - /// <param name="permission">New permissions</param> - /// <param name="throwOnError">Throw an exception instead of returning an error if the operation fails</param> - /// <returns>True if the reprotection was successful or if <paramref name="throwOnError"/> is true, false otherwise</returns> - /// <exception cref="WindowsApiException">If <paramref name="throwOnError"/> is true, it is thrown when the Windows API returns an error reprotecting the memory</exception> - private bool ReprotectViewInternal(IntPtr address, IntPtr size, MemoryPermission permission, bool throwOnError) - { - ulong reprotectAddress = (ulong)address; - ulong reprotectSize = (ulong)size; - ulong endAddress = reprotectAddress + reprotectSize; - - bool success = true; - - lock (_mappings) - { - RangeNode<ulong> node = _mappings.GetNodeByKey(reprotectAddress); - RangeNode<ulong> successorNode; - - for (; node != null; node = successorNode) - { - successorNode = node.Successor; - var overlap = node; - - ulong mappedAddress = overlap.Start; - ulong mappedSize = overlap.End - overlap.Start; - - if (mappedAddress < reprotectAddress) - { - ulong delta = reprotectAddress - mappedAddress; - mappedAddress = reprotectAddress; - mappedSize -= delta; - } - - ulong mappedEndAddress = mappedAddress + mappedSize; - - if (mappedEndAddress > endAddress) - { - ulong delta = mappedEndAddress - endAddress; - mappedSize -= delta; - } - - if (!WindowsApi.VirtualProtect((IntPtr)mappedAddress, (IntPtr)mappedSize, WindowsApi.GetProtection(permission), out _)) - { - if (throwOnError) - { - throw new WindowsApiException("VirtualProtect"); - } - - success = false; - } - - if (node.End >= endAddress) - { - break; - } - } - } - - UpdateProtection(reprotectAddress, reprotectSize, permission); - - return success; - } - - /// <summary> - /// Checks the result of a VirtualFree operation, throwing if needed. - /// </summary> - /// <param name="success">Operation result</param> - /// <exception cref="WindowsApiException">Thrown if <paramref name="success"/> is false</exception> - private static void CheckFreeResult(bool success) - { - if (!success) - { - throw new WindowsApiException("VirtualFree"); - } - } - - /// <summary> - /// Adds an offset to a backing offset. This will do nothing if the backing offset is the special "unmapped" value. - /// </summary> - /// <param name="backingOffset">Backing offset</param> - /// <param name="offset">Offset to be added</param> - /// <returns>Added offset or just <paramref name="backingOffset"/> if the region is unmapped</returns> - private static ulong AddBackingOffset(ulong backingOffset, ulong offset) - { - if (backingOffset == ulong.MaxValue) - { - return backingOffset; - } - - return backingOffset + offset; - } - - /// <summary> - /// Checks if a region is unmapped. - /// </summary> - /// <param name="backingOffset">Backing offset to check</param> - /// <returns>True if the backing offset is the special "unmapped" value, false otherwise</returns> - private static bool IsMapped(ulong backingOffset) - { - return backingOffset != ulong.MaxValue; - } - - /// <summary> - /// Adds a protection to the list of protections. - /// </summary> - /// <param name="address">Address of the protected region</param> - /// <param name="size">Size of the protected region in bytes</param> - /// <param name="permission">Memory permissions of the region</param> - private void UpdateProtection(ulong address, ulong size, MemoryPermission permission) - { - ulong endAddress = address + size; - - lock (_protections) - { - RangeNode<MemoryPermission> node = _protections.GetNodeByKey(address); - - if (node != null && - node.Start <= address && - node.End >= endAddress && - node.Value == permission) - { - return; - } - - RangeNode<MemoryPermission> successorNode; - - ulong startAddress = address; - - for (; node != null; node = successorNode) - { - successorNode = node.Successor; - var protection = node; - - ulong protAddress = protection.Start; - ulong protEndAddress = protection.End; - MemoryPermission protPermission = protection.Value; - - _protections.Remove(protection); - - if (protPermission == permission) - { - if (startAddress > protAddress) - { - startAddress = protAddress; - } - - if (endAddress < protEndAddress) - { - endAddress = protEndAddress; - } - } - else - { - if (startAddress > protAddress) - { - _protections.Add(new RangeNode<MemoryPermission>(protAddress, startAddress, protPermission)); - } - - if (endAddress < protEndAddress) - { - _protections.Add(new RangeNode<MemoryPermission>(endAddress, protEndAddress, protPermission)); - } - } - - if (node.End >= endAddress) - { - break; - } - } - - _protections.Add(new RangeNode<MemoryPermission>(startAddress, endAddress, permission)); - } - } - - /// <summary> - /// Removes protection from the list of protections. - /// </summary> - /// <param name="address">Address of the protected region</param> - /// <param name="size">Size of the protected region in bytes</param> - private void RemoveProtection(ulong address, ulong size) - { - ulong endAddress = address + size; - - lock (_protections) - { - RangeNode<MemoryPermission> node = _protections.GetNodeByKey(address); - RangeNode<MemoryPermission> successorNode; - - for (; node != null; node = successorNode) - { - successorNode = node.Successor; - var protection = node; - - ulong protAddress = protection.Start; - ulong protEndAddress = protection.End; - MemoryPermission protPermission = protection.Value; - - _protections.Remove(protection); - - if (address > protAddress) - { - _protections.Add(new RangeNode<MemoryPermission>(protAddress, address, protPermission)); - } - - if (endAddress < protEndAddress) - { - _protections.Add(new RangeNode<MemoryPermission>(endAddress, protEndAddress, protPermission)); - } - - if (node.End >= endAddress) - { - break; - } - } - } - } - - /// <summary> - /// Restores the protection of a given memory region that was remapped, using the protections list. - /// </summary> - /// <param name="address">Address of the remapped region</param> - /// <param name="size">Size of the remapped region in bytes</param> - private void RestoreRangeProtection(ulong address, ulong size) - { - ulong endAddress = address + size; - var overlaps = new RangeNode<MemoryPermission>[InitialOverlapsSize]; - int count; - - lock (_protections) - { - count = _protections.GetNodes(address, endAddress, ref overlaps); - } - - ulong startAddress = address; - - for (int index = 0; index < count; index++) - { - var protection = overlaps[index]; - - // If protection is R/W we don't need to reprotect as views are initially mapped as R/W. - if (protection.Value == MemoryPermission.ReadAndWrite) - { - continue; - } - - ulong protAddress = protection.Start; - ulong protEndAddress = protection.End; - - if (protAddress < address) - { - protAddress = address; - } - - if (protEndAddress > endAddress) - { - protEndAddress = endAddress; - } - - ReprotectViewInternal((IntPtr)protAddress, (IntPtr)(protEndAddress - protAddress), protection.Value, true); - } - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Memory/WindowsShared/WindowsApi.cs b/Ryujinx.Memory/WindowsShared/WindowsApi.cs deleted file mode 100644 index 67e704ea..00000000 --- a/Ryujinx.Memory/WindowsShared/WindowsApi.cs +++ /dev/null @@ -1,101 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -namespace Ryujinx.Memory.WindowsShared -{ - static partial class WindowsApi - { - public static readonly IntPtr InvalidHandleValue = new IntPtr(-1); - public static readonly IntPtr CurrentProcessHandle = new IntPtr(-1); - - [LibraryImport("kernel32.dll", SetLastError = true)] - public static partial IntPtr VirtualAlloc( - IntPtr lpAddress, - IntPtr dwSize, - AllocationType flAllocationType, - MemoryProtection flProtect); - - [LibraryImport("KernelBase.dll", SetLastError = true)] - public static partial IntPtr VirtualAlloc2( - IntPtr process, - IntPtr lpAddress, - IntPtr dwSize, - AllocationType flAllocationType, - MemoryProtection flProtect, - IntPtr extendedParameters, - ulong parameterCount); - - [LibraryImport("kernel32.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static partial bool VirtualProtect( - IntPtr lpAddress, - IntPtr dwSize, - MemoryProtection flNewProtect, - out MemoryProtection lpflOldProtect); - - [LibraryImport("kernel32.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static partial bool VirtualFree(IntPtr lpAddress, IntPtr dwSize, AllocationType dwFreeType); - - [LibraryImport("kernel32.dll", SetLastError = true, EntryPoint = "CreateFileMappingW")] - public static partial IntPtr CreateFileMapping( - IntPtr hFile, - IntPtr lpFileMappingAttributes, - FileMapProtection flProtect, - uint dwMaximumSizeHigh, - uint dwMaximumSizeLow, - [MarshalAs(UnmanagedType.LPWStr)] string lpName); - - [LibraryImport("kernel32.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static partial bool CloseHandle(IntPtr hObject); - - [LibraryImport("kernel32.dll", SetLastError = true)] - public static partial IntPtr MapViewOfFile( - IntPtr hFileMappingObject, - uint dwDesiredAccess, - uint dwFileOffsetHigh, - uint dwFileOffsetLow, - IntPtr dwNumberOfBytesToMap); - - [LibraryImport("KernelBase.dll", SetLastError = true)] - public static partial IntPtr MapViewOfFile3( - IntPtr hFileMappingObject, - IntPtr process, - IntPtr baseAddress, - ulong offset, - IntPtr dwNumberOfBytesToMap, - ulong allocationType, - MemoryProtection dwDesiredAccess, - IntPtr extendedParameters, - ulong parameterCount); - - [LibraryImport("kernel32.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static partial bool UnmapViewOfFile(IntPtr lpBaseAddress); - - [LibraryImport("KernelBase.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static partial bool UnmapViewOfFile2(IntPtr process, IntPtr lpBaseAddress, ulong unmapFlags); - - [LibraryImport("kernel32.dll")] - public static partial uint GetLastError(); - - [LibraryImport("kernel32.dll")] - public static partial int GetCurrentThreadId(); - - public static MemoryProtection GetProtection(MemoryPermission permission) - { - return permission switch - { - MemoryPermission.None => MemoryProtection.NoAccess, - MemoryPermission.Read => MemoryProtection.ReadOnly, - MemoryPermission.ReadAndWrite => MemoryProtection.ReadWrite, - MemoryPermission.ReadAndExecute => MemoryProtection.ExecuteRead, - MemoryPermission.ReadWriteExecute => MemoryProtection.ExecuteReadWrite, - MemoryPermission.Execute => MemoryProtection.Execute, - _ => throw new MemoryProtectionException(permission) - }; - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Memory/WindowsShared/WindowsApiException.cs b/Ryujinx.Memory/WindowsShared/WindowsApiException.cs deleted file mode 100644 index 3140d705..00000000 --- a/Ryujinx.Memory/WindowsShared/WindowsApiException.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; - -namespace Ryujinx.Memory.WindowsShared -{ - class WindowsApiException : Exception - { - public WindowsApiException() - { - } - - public WindowsApiException(string functionName) : base(CreateMessage(functionName)) - { - } - - public WindowsApiException(string functionName, Exception inner) : base(CreateMessage(functionName), inner) - { - } - - private static string CreateMessage(string functionName) - { - return $"{functionName} returned error code 0x{WindowsApi.GetLastError():X}."; - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Memory/WindowsShared/WindowsFlags.cs b/Ryujinx.Memory/WindowsShared/WindowsFlags.cs deleted file mode 100644 index ca69cfe9..00000000 --- a/Ryujinx.Memory/WindowsShared/WindowsFlags.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; - -namespace Ryujinx.Memory.WindowsShared -{ - [Flags] - enum AllocationType : uint - { - CoalescePlaceholders = 0x1, - PreservePlaceholder = 0x2, - Commit = 0x1000, - Reserve = 0x2000, - Decommit = 0x4000, - ReplacePlaceholder = 0x4000, - Release = 0x8000, - ReservePlaceholder = 0x40000, - Reset = 0x80000, - Physical = 0x400000, - TopDown = 0x100000, - WriteWatch = 0x200000, - LargePages = 0x20000000 - } - - [Flags] - enum MemoryProtection : uint - { - NoAccess = 0x01, - ReadOnly = 0x02, - ReadWrite = 0x04, - WriteCopy = 0x08, - Execute = 0x10, - ExecuteRead = 0x20, - ExecuteReadWrite = 0x40, - ExecuteWriteCopy = 0x80, - GuardModifierflag = 0x100, - NoCacheModifierflag = 0x200, - WriteCombineModifierflag = 0x400 - } - - [Flags] - enum FileMapProtection : uint - { - PageReadonly = 0x02, - PageReadWrite = 0x04, - PageWriteCopy = 0x08, - PageExecuteRead = 0x20, - PageExecuteReadWrite = 0x40, - SectionCommit = 0x8000000, - SectionImage = 0x1000000, - SectionNoCache = 0x10000000, - SectionReserve = 0x4000000 - } -} |
