diff --git a/trunk/ProcessHacker.Native/Api/Functions.cs b/trunk/ProcessHacker.Native/Api/Functions.cs index 963016d38..49854a5c5 100644 --- a/trunk/ProcessHacker.Native/Api/Functions.cs +++ b/trunk/ProcessHacker.Native/Api/Functions.cs @@ -132,6 +132,12 @@ namespace ProcessHacker.Native.Api #region Files + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool GetFileSizeEx( + [In] IntPtr FileHandle, + [Out] out long FileSize + ); + [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern int QueryDosDevice( [In] [Optional] string DeviceName, diff --git a/trunk/ProcessHacker.Native/Api/NativeFunctions.cs b/trunk/ProcessHacker.Native/Api/NativeFunctions.cs index 04bd281e1..67421466a 100644 --- a/trunk/ProcessHacker.Native/Api/NativeFunctions.cs +++ b/trunk/ProcessHacker.Native/Api/NativeFunctions.cs @@ -296,8 +296,19 @@ namespace ProcessHacker.Native.Api [In] SectionAccess DesiredAccess, [In] [Optional] ref ObjectAttributes ObjectAttributes, [In] [Optional] ref long MaximumSize, - [In] int PageAttributes, - [In] int SectionAttributes, + [In] MemoryProtection PageAttributes, + [In] SectionAttributes SectionAttributes, + [In] [Optional] IntPtr FileHandle + ); + + [DllImport("ntdll.dll")] + public static extern NtStatus NtCreateSection( + [Out] out IntPtr SectionHandle, + [In] SectionAccess DesiredAccess, + [In] [Optional] ref ObjectAttributes ObjectAttributes, + [In] [Optional] IntPtr MaximumSize, + [In] MemoryProtection PageAttributes, + [In] SectionAttributes SectionAttributes, [In] [Optional] IntPtr FileHandle ); diff --git a/trunk/ProcessHacker.Native/IntPtrExtensions.cs b/trunk/ProcessHacker.Native/IntPtrExtensions.cs index c8a1a8942..e93f705ae 100644 --- a/trunk/ProcessHacker.Native/IntPtrExtensions.cs +++ b/trunk/ProcessHacker.Native/IntPtrExtensions.cs @@ -59,6 +59,11 @@ namespace ProcessHacker.Native return Increment(ptr, -value); } + public static IntPtr Decrement(this IntPtr ptr, long value) + { + return Increment(ptr, -value); + } + public static T ElementAt(this IntPtr ptr, int index) { var offset = Marshal.SizeOf(typeof(T)) * index; @@ -77,6 +82,17 @@ namespace ProcessHacker.Native } } + public static IntPtr Increment(this IntPtr ptr, long value) + { + unchecked + { + if (IntPtr.Size == sizeof(Int32)) + return new IntPtr(ptr.ToInt32() + value); + else + return new IntPtr(ptr.ToInt64() + value); + } + } + public static IntPtr Increment(this IntPtr ptr, IntPtr ptr2) { unchecked diff --git a/trunk/ProcessHacker.Native/Memory/MemoryAlloc.cs b/trunk/ProcessHacker.Native/Memory/MemoryAlloc.cs index 7702abc39..110abc899 100644 --- a/trunk/ProcessHacker.Native/Memory/MemoryAlloc.cs +++ b/trunk/ProcessHacker.Native/Memory/MemoryAlloc.cs @@ -102,6 +102,35 @@ namespace ProcessHacker.Native this.Dispose(false); } + public MemoryAllocStream GetStream() + { + return new MemoryAllocStream(this); + } + + public byte[] ReadBytes(int length) + { + return this.ReadBytes(0, length); + } + + public byte[] ReadBytes(int offset, int length) + { + byte[] buffer = new byte[length]; + + this.ReadBytes(offset, buffer, 0, length); + + return buffer; + } + + public void ReadBytes(byte[] buffer, int startIndex, int length) + { + this.ReadBytes(0, buffer, startIndex, length); + } + + public void ReadBytes(int offset, byte[] buffer, int startIndex, int length) + { + Marshal.Copy(_memory.Increment(offset), buffer, startIndex, length); + } + /// /// Reads a signed integer. /// @@ -219,7 +248,7 @@ namespace ProcessHacker.Native public void WriteBytes(int offset, byte[] b) { - Marshal.Copy(b, 0, new IntPtr(this + offset), b.Length); + Marshal.Copy(b, 0, _memory.Increment(offset), b.Length); } public void WriteInt16(int offset, short i) diff --git a/trunk/ProcessHacker.Native/Memory/MemoryAllocStream.cs b/trunk/ProcessHacker.Native/Memory/MemoryAllocStream.cs new file mode 100644 index 000000000..60e9b0105 --- /dev/null +++ b/trunk/ProcessHacker.Native/Memory/MemoryAllocStream.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Runtime.InteropServices; + +namespace ProcessHacker.Native +{ + public class MemoryAllocStream : Stream + { + private MemoryAlloc _memory; + private long _position = 0; + + public MemoryAllocStream(MemoryAlloc memory) + { + _memory = memory; + } + + public override bool CanRead + { + get { return true; } + } + + public override bool CanSeek + { + get { return true; } + } + + public override bool CanTimeout + { + get { return false; } + } + + public override bool CanWrite + { + get { return true; } + } + + public override void Flush() + { + // Do nothing + } + + public override long Length + { + get { return _memory.Size; } + } + + public override long Position + { + get { return _position; } + set { _position = value; } + } + + public override int Read(byte[] buffer, int offset, int count) + { + Marshal.Copy(_memory.Memory.Increment(_position += count), buffer, offset, count); + + return count; + } + + public override int ReadByte() + { + return Marshal.ReadByte(_memory.Memory.Increment(_position++)); + } + + public override long Seek(long offset, SeekOrigin origin) + { + if (origin == SeekOrigin.Begin) + _position = offset; + else if (origin == SeekOrigin.Current) + _position += offset; + else if (origin == SeekOrigin.End) + _position = _memory.Size + offset; + + return _position; + } + + public override void SetLength(long value) + { + throw new NotSupportedException(); + } + + public override void Write(byte[] buffer, int offset, int count) + { + Marshal.Copy(buffer, offset, _memory.Memory.Increment(_position += count), count); + } + + public override void WriteByte(byte value) + { + Marshal.WriteByte(_memory.Memory.Increment(_position++), value); + } + } +} diff --git a/trunk/ProcessHacker.Native/Memory/Section.cs b/trunk/ProcessHacker.Native/Memory/Section.cs new file mode 100644 index 000000000..f18e5abdb --- /dev/null +++ b/trunk/ProcessHacker.Native/Memory/Section.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Text; +using ProcessHacker.Native.Api; +using ProcessHacker.Native.Objects; +using ProcessHacker.Native.Security; + +namespace ProcessHacker.Native +{ + public class Section : NativeObject + { + private MemoryProtection _originalProtection; + + public Section(FileHandle fileHandle) + : this(fileHandle, MemoryProtection.ReadWrite) + { } + + public Section(FileHandle fileHandle, MemoryProtection protection) + : this(fileHandle, false, protection) + { } + + public Section(FileHandle fileHandle, bool image, MemoryProtection protection) + : this(null, fileHandle, image, protection) + { } + + public Section(string name, FileHandle fileHandle, bool image, MemoryProtection protection) + { + _originalProtection = protection; + this.Handle = SectionHandle.Create( + SectionAccess.All, + fileHandle.GetSize(), + image ? SectionAttributes.Image : 0, + protection, + fileHandle + ); + } + + public Section(long maximumSize) + : this(maximumSize, MemoryProtection.ReadWrite) + { } + + public Section(long maximumSize, MemoryProtection protection) + : this(null, maximumSize, protection) + { } + + public Section(string name, long maximumSize, MemoryProtection protection) + { + _originalProtection = protection; + this.Handle = SectionHandle.Create( + SectionAccess.All, + maximumSize, + SectionAttributes.Commit, + protection + ); + } + + public void Extend(long newSize) + { + this.Handle.Extend(newSize); + } + + public SectionView MapView(int size) + { + return this.MapView(size, _originalProtection); + } + + public SectionView MapView(int size, MemoryProtection protection) + { + return this.Handle.MapView(size, protection); + } + } +} diff --git a/trunk/ProcessHacker.Native/Objects/FileHandle.cs b/trunk/ProcessHacker.Native/Objects/FileHandle.cs index bb61ad2b0..02a6eb3cd 100644 --- a/trunk/ProcessHacker.Native/Objects/FileHandle.cs +++ b/trunk/ProcessHacker.Native/Objects/FileHandle.cs @@ -31,9 +31,26 @@ namespace ProcessHacker.Native.Objects /// public class FileHandle : NativeHandle { + public static FileHandle FromHandle(IntPtr handle) + { + return new FileHandle(handle, false); + } + protected FileHandle() { } + private FileHandle(IntPtr handle, bool owned) + : base(handle, owned) + { } + + public FileHandle(string fileName, FileAccess desiredAccess) + : this(fileName, desiredAccess, FileShareMode.Exclusive) + { } + + public FileHandle(string fileName, FileAccess desiredAccess, FileShareMode shareMode) + : this(fileName, desiredAccess, shareMode, FileCreationDisposition.OpenExisting) + { } + public FileHandle(string fileName, FileAccess desiredAccess, FileShareMode shareMode, FileCreationDisposition creationDisposition) { @@ -43,13 +60,15 @@ namespace ProcessHacker.Native.Objects Win32.ThrowLastError(); } - public FileHandle(string fileName, FileAccess desiredAccess, FileShareMode shareMode) - : this(fileName, desiredAccess, shareMode, FileCreationDisposition.OpenExisting) - { } + public long GetSize() + { + long fileSize; - public FileHandle(string fileName, FileAccess desiredAccess) - : this(fileName, desiredAccess, FileShareMode.Exclusive) - { } + if (!Win32.GetFileSizeEx(this, out fileSize)) + Win32.ThrowLastError(); + + return fileSize; + } /// /// Sends an I/O control message to the device's associated driver. @@ -127,6 +146,20 @@ namespace ProcessHacker.Native.Objects return isb.Information.ToInt32(); } + /// + /// Reads data from the file. + /// + /// The length to read. + /// The read data. + public byte[] Read(int length) + { + byte[] buffer = new byte[length]; + + this.Read(buffer); + + return buffer; + } + /// /// Reads data from the file. /// @@ -142,20 +175,6 @@ namespace ProcessHacker.Native.Objects return bytesRead; } - /// - /// Reads data from the file. - /// - /// The length to read. - /// The read data. - public byte[] Read(int length) - { - byte[] buffer = new byte[length]; - - this.Read(buffer); - - return buffer; - } - /// /// Writes data to the file. /// diff --git a/trunk/ProcessHacker.Native/Objects/SectionHandle.cs b/trunk/ProcessHacker.Native/Objects/SectionHandle.cs index 2700c729e..4bae40de8 100644 --- a/trunk/ProcessHacker.Native/Objects/SectionHandle.cs +++ b/trunk/ProcessHacker.Native/Objects/SectionHandle.cs @@ -38,7 +38,28 @@ namespace ProcessHacker.Native.Objects FileHandle fileHandle ) { - return Create(access, null, 0, sectionAttributes, pageAttributes, fileHandle); + return Create(access, 0, sectionAttributes, pageAttributes, fileHandle); + } + + public static SectionHandle Create( + SectionAccess access, + long maximumSize, + SectionAttributes sectionAttributes, + MemoryProtection pageAttributes, + FileHandle fileHandle + ) + { + return Create(access, null, maximumSize, sectionAttributes, pageAttributes, fileHandle); + } + + public static SectionHandle Create( + SectionAccess access, + long maximumSize, + SectionAttributes sectionAttributes, + MemoryProtection pageAttributes + ) + { + return Create(access, null, maximumSize, sectionAttributes, pageAttributes, null); } public static SectionHandle Create( @@ -70,15 +91,32 @@ namespace ProcessHacker.Native.Objects try { - if ((status = Win32.NtCreateSection( - out handle, - access, - ref oa, - ref maximumSize, - (int)pageAttributes, - (int)sectionAttributes, - fileHandle)) >= NtStatus.Error) - Win32.ThrowLastError(status); + if (maximumSize != 0) + { + if ((status = Win32.NtCreateSection( + out handle, + access, + ref oa, + ref maximumSize, + pageAttributes, + sectionAttributes, + fileHandle != null ? fileHandle : IntPtr.Zero + )) >= NtStatus.Error) + Win32.ThrowLastError(status); + } + else + { + if ((status = Win32.NtCreateSection( + out handle, + access, + ref oa, + IntPtr.Zero, + pageAttributes, + sectionAttributes, + fileHandle != null ? fileHandle : IntPtr.Zero + )) >= NtStatus.Error) + Win32.ThrowLastError(status); + } } finally { @@ -156,6 +194,35 @@ namespace ProcessHacker.Native.Objects return sii; } + public SectionView MapView(int size, MemoryProtection protection) + { + return this.MapView(IntPtr.Zero, new IntPtr(size), protection); + } + + public SectionView MapView(IntPtr baseAddress, IntPtr size, MemoryProtection protection) + { + return this.MapView(ProcessHandle.GetCurrent(), baseAddress, size, protection); + } + + public SectionView MapView( + ProcessHandle processHandle, + IntPtr baseAddress, + IntPtr size, + MemoryProtection protection + ) + { + return this.MapView( + processHandle, + baseAddress, + size, + 0, + size, + SectionInherit.ViewShare, + 0, + protection + ); + } + public SectionView MapView( ProcessHandle processHandle, IntPtr baseAddress, @@ -185,34 +252,5 @@ namespace ProcessHacker.Native.Objects return new SectionView(baseAddress, commitSize); } - - public SectionView MapView( - ProcessHandle processHandle, - IntPtr baseAddress, - IntPtr size, - MemoryProtection protection - ) - { - return this.MapView( - processHandle, - baseAddress, - size, - 0, - size, - SectionInherit.ViewShare, - 0, - protection - ); - } - - public SectionView MapView(IntPtr baseAddress, IntPtr size, MemoryProtection protection) - { - return this.MapView(ProcessHandle.GetCurrent(), baseAddress, size, protection); - } - - public SectionView MapView(int size, MemoryProtection protection) - { - return this.MapView(IntPtr.Zero, new IntPtr(size), protection); - } } } diff --git a/trunk/ProcessHacker.Native/ProcessHacker.Native.csproj b/trunk/ProcessHacker.Native/ProcessHacker.Native.csproj index dff95689d..7ea4f3733 100644 --- a/trunk/ProcessHacker.Native/ProcessHacker.Native.csproj +++ b/trunk/ProcessHacker.Native/ProcessHacker.Native.csproj @@ -49,6 +49,8 @@ + +