Dss
StreamIStream.cs
// dnlib: See LICENSE.txt for more info
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
namespace dnlib.DotNet.Pdb.Dss {
///
/// Implements and uses a as the underlying
/// stream.
///
sealed clast StreamIStream : IStream {
readonly Stream stream;
readonly string name;
const int STG_E_INVALIDFUNCTION = unchecked((int)0x80030001);
///
/// Constructor
///
/// Source stream
public StreamIStream(Stream stream)
: this(stream, string.Empty) {
}
///
/// Constructor
///
/// Source stream
/// Name of original file or null if unknown.
public StreamIStream(Stream stream, string name) {
if (stream == null)
throw new ArgumentNullException("stream");
this.stream = stream;
this.name = name ?? string.Empty;
}
///
public void Clone(out IStream ppstm) {
Marshal.ThrowExceptionForHR(STG_E_INVALIDFUNCTION);
throw new Exception();
}
///
public void Commit(int grfCommitFlags) {
stream.Flush();
}
///
public void CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten) {
if (cb > int.MaxValue)
cb = int.MaxValue;
else if (cb < 0)
cb = 0;
int sizeToRead = (int)cb;
if (stream.Position + sizeToRead < sizeToRead || stream.Position + sizeToRead > stream.Length)
sizeToRead = (int)(stream.Length - Math.Min(stream.Position, stream.Length));
var buffer = new byte[sizeToRead];
Read(buffer, sizeToRead, pcbRead);
if (pcbRead != IntPtr.Zero)
Marshal.WriteInt64(pcbRead, Marshal.ReadInt32(pcbRead));
pstm.Write(buffer, buffer.Length, pcbWritten);
if (pcbWritten != IntPtr.Zero)
Marshal.WriteInt64(pcbWritten, Marshal.ReadInt32(pcbWritten));
}
///
public void LockRegion(long libOffset, long cb, int dwLockType) {
Marshal.ThrowExceptionForHR(STG_E_INVALIDFUNCTION);
}
///
public void Read(byte[] pv, int cb, IntPtr pcbRead) {
if (cb < 0)
cb = 0;
cb = stream.Read(pv, 0, cb);
if (pcbRead != IntPtr.Zero)
Marshal.WriteInt32(pcbRead, cb);
}
///
public void Revert() {
}
enum STREAM_SEEK {
SET = 0,
CUR = 1,
END = 2,
}
///
public void Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition) {
switch ((STREAM_SEEK)dwOrigin) {
case STREAM_SEEK.SET:
stream.Position = dlibMove;
break;
case STREAM_SEEK.CUR:
stream.Position += dlibMove;
break;
case STREAM_SEEK.END:
stream.Position = stream.Length + dlibMove;
break;
}
if (plibNewPosition != IntPtr.Zero)
Marshal.WriteInt64(plibNewPosition, stream.Position);
}
///
public void SetSize(long libNewSize) {
stream.SetLength(libNewSize);
}
enum STATFLAG {
DEFAULT = 0,
NONAME = 1,
NOOPEN = 2,
}
enum STGTY {
STORAGE = 1,
STREAM = 2,
LOCKBYTES = 3,
PROPERTY = 4,
}
///
public void Stat(out System.Runtime.InteropServices.ComTypes.STATSTG pstatstg, int grfStatFlag) {
var s = new System.Runtime.InteropServices.ComTypes.STATSTG();
// s.atime = ???;
s.cbSize = stream.Length;
s.clsid = Guid.Empty;
// s.ctime = ???;
s.grfLocksSupported = 0;
s.grfMode = 2;
s.grfStateBits = 0;
// s.mtime = ???;
if ((grfStatFlag & (int)STATFLAG.NONAME) == 0)
s.pwcsName = name;
s.reserved = 0;
s.type = (int)STGTY.STREAM;
pstatstg = s;
}
///
public void UnlockRegion(long libOffset, long cb, int dwLockType) {
Marshal.ThrowExceptionForHR(STG_E_INVALIDFUNCTION);
}
///
public void Write(byte[] pv, int cb, IntPtr pcbWritten) {
stream.Write(pv, 0, cb);
if (pcbWritten != IntPtr.Zero)
Marshal.WriteInt32(pcbWritten, cb);
}
}
}