mirror of
https://github.com/ReneLergner/WPinternals.git
synced 2026-06-14 03:16:40 +10:00
255 lines
8.4 KiB
C#
255 lines
8.4 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace WPinternalsSDK
|
|
{
|
|
public class FileStream : Stream
|
|
{
|
|
public FileStream(string Path, FileStreamMode Mode)
|
|
{
|
|
try
|
|
{
|
|
this.path = Path;
|
|
this.mode = Mode;
|
|
switch (this.mode)
|
|
{
|
|
case FileStreamMode.Read:
|
|
this.length = (uint)FileSystem.GetFileSize(this.path);
|
|
if (this.length > 0U)
|
|
{
|
|
this.hFile = Win32.CreateFile(this.path, (FileAccess)2147483648U, ShareMode.Read | ShareMode.Write, IntPtr.Zero, CreationDisposition.OpenExisting, FileAttributes.Normal, IntPtr.Zero);
|
|
}
|
|
break;
|
|
case FileStreamMode.Write:
|
|
this.hFile = Win32.CreateFile(this.path, FileAccess.GenericWrite, ShareMode.None, IntPtr.Zero, CreationDisposition.CreateAlways, FileAttributes.Normal, IntPtr.Zero);
|
|
break;
|
|
case FileStreamMode.ReadWrite:
|
|
if (FileSystem.FileExists(this.path))
|
|
{
|
|
this.length = (uint)FileSystem.GetFileSize(this.path);
|
|
}
|
|
this.hFile = Win32.CreateFile(this.path, (FileAccess)3221225472U, ShareMode.None, IntPtr.Zero, CreationDisposition.OpenAlways, FileAttributes.Normal, IntPtr.Zero);
|
|
break;
|
|
}
|
|
this.open = true;
|
|
}
|
|
catch
|
|
{
|
|
throw;
|
|
}
|
|
}
|
|
|
|
public override bool CanRead
|
|
{
|
|
get
|
|
{
|
|
return (this.mode == FileStreamMode.Read || this.mode == FileStreamMode.ReadWrite) && this.open;
|
|
}
|
|
}
|
|
|
|
public override bool CanSeek
|
|
{
|
|
get
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public override bool CanWrite
|
|
{
|
|
get
|
|
{
|
|
return (this.mode == FileStreamMode.Write || this.mode == FileStreamMode.ReadWrite) && this.open;
|
|
}
|
|
}
|
|
|
|
public override void Flush()
|
|
{
|
|
}
|
|
|
|
public override long Length
|
|
{
|
|
get
|
|
{
|
|
return (long)((ulong)((this.mode == FileStreamMode.Read) ? this.length : this.position));
|
|
}
|
|
}
|
|
|
|
public override long Position
|
|
{
|
|
get
|
|
{
|
|
return (long)((ulong)this.position);
|
|
}
|
|
set
|
|
{
|
|
if (value != (long)((ulong)this.position))
|
|
{
|
|
if (value < 0L || value > -1)
|
|
{
|
|
throw new IndexOutOfRangeException("Position must be unsigned 32 bit");
|
|
}
|
|
int num;
|
|
if (Win32.SetFilePointer(this.hFile, (int)value, out num, MoveMethod.Begin) == 4294967295U)
|
|
{
|
|
throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to set position");
|
|
}
|
|
this.position = (uint)value;
|
|
}
|
|
}
|
|
}
|
|
|
|
public override int Read(byte[] buffer, int offset, int count)
|
|
{
|
|
if (!this.open)
|
|
{
|
|
throw new InvalidOperationException("Stream is closed");
|
|
}
|
|
if (this.mode != FileStreamMode.Read && this.mode != FileStreamMode.ReadWrite)
|
|
{
|
|
throw new InvalidOperationException("Cannot read from this stream");
|
|
}
|
|
if (count < 0)
|
|
{
|
|
throw new ArgumentException("Count must have a positive value");
|
|
}
|
|
uint num = this.length - this.position;
|
|
if (num < 0U)
|
|
{
|
|
num = 0U;
|
|
}
|
|
if (buffer == null)
|
|
{
|
|
throw new ArgumentNullException("Buffer cannot be null");
|
|
}
|
|
if ((ulong)num > (ulong)((long)count))
|
|
{
|
|
num = (uint)count;
|
|
}
|
|
if (num > 0U)
|
|
{
|
|
if ((long)offset + (long)((ulong)num) > (long)buffer.Length)
|
|
{
|
|
throw new ArgumentException("Buffer too small");
|
|
}
|
|
if (!Win32.ReadFile(this.hFile, buffer, (uint)count, out num, UIntPtr.Zero))
|
|
{
|
|
throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to read file");
|
|
}
|
|
this.position += num;
|
|
}
|
|
return (int)num;
|
|
}
|
|
|
|
public override long Seek(long offset, SeekOrigin origin)
|
|
{
|
|
if (offset < -2147483648L || offset > 2147483647L)
|
|
{
|
|
throw new IndexOutOfRangeException("Offset must be in 32 bit range");
|
|
}
|
|
int num2;
|
|
uint num = Win32.SetFilePointer(this.hFile, (int)offset, out num2, (MoveMethod)origin);
|
|
if (num == 4294967295U)
|
|
{
|
|
throw new Win32Exception(Marshal.GetLastWin32Error(), "Seek failed");
|
|
}
|
|
this.position = num;
|
|
return (long)((ulong)this.position);
|
|
}
|
|
|
|
public override void SetLength(long value)
|
|
{
|
|
if (this.mode != FileStreamMode.ReadWrite)
|
|
{
|
|
throw new InvalidOperationException("Only possible to set the lenght when FileAccessMode is ReadWrite");
|
|
}
|
|
if (value < 0L || value > -1)
|
|
{
|
|
throw new IndexOutOfRangeException("Length must be unsigned 32 bit");
|
|
}
|
|
int num;
|
|
if (Win32.SetFilePointer(this.hFile, (int)value, out num, MoveMethod.Begin) == 4294967295U)
|
|
{
|
|
throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to set length");
|
|
}
|
|
if (!Win32.SetEndOfFile(this.hFile))
|
|
{
|
|
throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to set length");
|
|
}
|
|
if ((ulong)this.position > (ulong)value)
|
|
{
|
|
this.position = (uint)value;
|
|
}
|
|
if (Win32.SetFilePointer(this.hFile, (int)this.position, out num, MoveMethod.Begin) == 4294967295U)
|
|
{
|
|
throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to set length");
|
|
}
|
|
this.length = (uint)value;
|
|
}
|
|
|
|
public override void Write(byte[] buffer, int offset, int count)
|
|
{
|
|
if (!this.open)
|
|
{
|
|
throw new InvalidOperationException("Stream is closed");
|
|
}
|
|
if (this.mode != FileStreamMode.Write && this.mode != FileStreamMode.ReadWrite)
|
|
{
|
|
throw new InvalidOperationException("Cannot write to this stream");
|
|
}
|
|
if (count < 0)
|
|
{
|
|
throw new ArgumentException("Count must have a positive value");
|
|
}
|
|
uint num = (uint)(buffer.Length - offset);
|
|
if (buffer == null)
|
|
{
|
|
throw new ArgumentNullException("Buffer cannot be null");
|
|
}
|
|
if ((ulong)num > (ulong)((long)count))
|
|
{
|
|
num = (uint)count;
|
|
}
|
|
if ((long)count > (long)((ulong)num))
|
|
{
|
|
throw new ArgumentException("Buffer too small");
|
|
}
|
|
if (num > 0U)
|
|
{
|
|
if (!Win32.WriteFile(this.hFile, buffer, (uint)count, out num, UIntPtr.Zero))
|
|
{
|
|
throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to write file");
|
|
}
|
|
this.position += num;
|
|
if (this.length < this.position)
|
|
{
|
|
this.length = this.position;
|
|
}
|
|
}
|
|
}
|
|
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
if (this.open)
|
|
{
|
|
Win32.CloseHandle(this.hFile);
|
|
}
|
|
this.open = false;
|
|
base.Dispose(disposing);
|
|
}
|
|
|
|
private readonly string path;
|
|
|
|
private readonly FileStreamMode mode;
|
|
|
|
public bool open;
|
|
|
|
private uint position;
|
|
|
|
private uint length;
|
|
|
|
private IntPtr hFile = (IntPtr)(-1);
|
|
}
|
|
}
|