123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270 |
- using System;
- using System.Diagnostics.CodeAnalysis;
- using System.IO;
- using System.Runtime.InteropServices;
- using System.Security.Permissions;
- using HandyControl.Tools.Interop;
- namespace HandyControl.Data;
- // ReSharper disable once InconsistentNaming
- internal class GPStream : InteropValues.IStream
- {
- protected Stream DataStream;
- // to support seeking ahead of the stream length...
- long _virtualPosition = -1;
- internal GPStream(Stream stream)
- {
- if (!stream.CanSeek)
- {
- const int readBlock = 256;
- var bytes = new byte[readBlock];
- int readLen;
- var current = 0;
- do
- {
- if (bytes.Length < current + readBlock)
- {
- var newData = new byte[bytes.Length * 2];
- Array.Copy(bytes, newData, bytes.Length);
- bytes = newData;
- }
- readLen = stream.Read(bytes, current, readBlock);
- current += readLen;
- } while (readLen != 0);
- DataStream = new MemoryStream(bytes);
- }
- else
- {
- DataStream = stream;
- }
- }
- private void ActualizeVirtualPosition()
- {
- if (_virtualPosition == -1) return;
- if (_virtualPosition > DataStream.Length)
- DataStream.SetLength(_virtualPosition);
- DataStream.Position = _virtualPosition;
- _virtualPosition = -1;
- }
- public virtual InteropValues.IStream Clone()
- {
- NotImplemented();
- return null;
- }
- public virtual void Commit(int grfCommitFlags)
- {
- DataStream.Flush();
- // Extend the length of the file if needed.
- ActualizeVirtualPosition();
- }
- [
- UIPermission(SecurityAction.Demand, Window = UIPermissionWindow.AllWindows),
- SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.UnmanagedCode)
- ]
- public virtual long CopyTo(InteropValues.IStream pstm, long cb, long[] pcbRead)
- {
- const int bufsize = 4096;
- var buffer = Marshal.AllocHGlobal(bufsize);
- if (buffer == IntPtr.Zero) throw new OutOfMemoryException();
- long written = 0;
- try
- {
- while (written < cb)
- {
- var toRead = bufsize;
- if (written + toRead > cb) toRead = (int) (cb - written);
- var read = Read(buffer, toRead);
- if (read == 0) break;
- if (pstm.Write(buffer, read) != read)
- {
- throw EFail("Wrote an incorrect number of bytes");
- }
- written += read;
- }
- }
- finally
- {
- Marshal.FreeHGlobal(buffer);
- }
- if (pcbRead != null && pcbRead.Length > 0)
- {
- pcbRead[0] = written;
- }
- return written;
- }
- public virtual Stream GetDataStream()
- {
- return DataStream;
- }
- public virtual void LockRegion(long libOffset, long cb, int dwLockType)
- {
- }
- protected static ExternalException EFail(string msg)
- {
- throw new ExternalException(msg, InteropMethods.E_FAIL);
- }
- protected static void NotImplemented()
- {
- throw new ExternalException("NotImplemented");
- }
- public virtual int Read(IntPtr buf, int length)
- {
- var buffer = new byte[length];
- var count = Read(buffer, length);
- Marshal.Copy(buffer, 0, buf, length);
- return count;
- }
- public virtual int Read(byte[] buffer, int length)
- {
- ActualizeVirtualPosition();
- return DataStream.Read(buffer, 0, length);
- }
- public virtual void Revert()
- {
- NotImplemented();
- }
- public virtual long Seek(long offset, int origin)
- {
- var pos = _virtualPosition;
- if (_virtualPosition == -1)
- {
- pos = DataStream.Position;
- }
- var len = DataStream.Length;
- switch (origin)
- {
- case InteropValues.StreamConsts.STREAM_SEEK_SET:
- if (offset <= len)
- {
- DataStream.Position = offset;
- _virtualPosition = -1;
- }
- else
- {
- _virtualPosition = offset;
- }
- break;
- case InteropValues.StreamConsts.STREAM_SEEK_END:
- if (offset <= 0)
- {
- DataStream.Position = len + offset;
- _virtualPosition = -1;
- }
- else
- {
- _virtualPosition = len + offset;
- }
- break;
- case InteropValues.StreamConsts.STREAM_SEEK_CUR:
- if (offset + pos <= len)
- {
- DataStream.Position = pos + offset;
- _virtualPosition = -1;
- }
- else
- {
- _virtualPosition = offset + pos;
- }
- break;
- }
- return _virtualPosition != -1 ? _virtualPosition : DataStream.Position;
- }
- public virtual void SetSize(long value)
- {
- DataStream.SetLength(value);
- }
- public void Stat(IntPtr pstatstg, int grfStatFlag)
- {
- var stats = new STATSTG { cbSize = DataStream.Length };
- Marshal.StructureToPtr(stats, pstatstg, true);
- }
- public virtual void UnlockRegion(long libOffset, long cb, int dwLockType)
- {
- }
- public virtual int Write(IntPtr buf, int length)
- {
- var buffer = new byte[length];
- Marshal.Copy(buf, buffer, 0, length);
- return Write(buffer, length);
- }
- public virtual int Write(byte[] buffer, int length)
- {
- ActualizeVirtualPosition();
- DataStream.Write(buffer, 0, length);
- return length;
- }
- [StructLayout(LayoutKind.Sequential)]
- [SuppressMessage("ReSharper", "InconsistentNaming")]
- public class STATSTG
- {
- [SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources")]
- public IntPtr pwcsName = IntPtr.Zero;
- public int type;
- [MarshalAs(UnmanagedType.I8)]
- public long cbSize;
- [MarshalAs(UnmanagedType.I8)]
- public long mtime;
- [MarshalAs(UnmanagedType.I8)]
- public long ctime;
- [MarshalAs(UnmanagedType.I8)]
- public long atime;
- [MarshalAs(UnmanagedType.I4)]
- public int grfMode;
- [MarshalAs(UnmanagedType.I4)]
- public int grfLocksSupported;
- public int clsid_data1;
- [MarshalAs(UnmanagedType.I2)]
- public short clsid_data2;
- [MarshalAs(UnmanagedType.I2)]
- public short clsid_data3;
- [MarshalAs(UnmanagedType.U1)]
- public byte clsid_b0;
- [MarshalAs(UnmanagedType.U1)]
- public byte clsid_b1;
- [MarshalAs(UnmanagedType.U1)]
- public byte clsid_b2;
- [MarshalAs(UnmanagedType.U1)]
- public byte clsid_b3;
- [MarshalAs(UnmanagedType.U1)]
- public byte clsid_b4;
- [MarshalAs(UnmanagedType.U1)]
- public byte clsid_b5;
- [MarshalAs(UnmanagedType.U1)]
- public byte clsid_b6;
- [MarshalAs(UnmanagedType.U1)]
- public byte clsid_b7;
- [MarshalAs(UnmanagedType.I4)]
- public int grfStateBits;
- [MarshalAs(UnmanagedType.I4)]
- public int reserved;
- }
- }
|