using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Runtime.InteropServices; namespace Biff8Excel.COM { public sealed class COMStream : System.IO.Stream, IDisposable { private bool disposed; private IStreamRef stream; IntPtr PWrite; public COMStream(IStreamRef stream) { this.stream = stream; PWrite = IntPtr.Zero; } ~COMStream() { this.Dispose(); } public void Dispose() { if (!this.disposed) { Marshal.ReleaseComObject(this.stream); this.stream = null; this.disposed = true; } GC.SuppressFinalize(this); } public IStreamRef UnderlyingStream { get { return this.stream; } } public override bool CanRead { get { return true; } } public override bool CanSeek { get { return true; } } public override bool CanWrite { get { return true; } } public override void Flush() { this.stream.Commit(0); } public override long Length { get { if (this.stream == null) throw new ObjectDisposedException("Invalid stream object."); STATSTG statstg; this.stream.Stat(out statstg, 1 /**//* STATSFLAG_NONAME*/ ); return statstg.cbSize; } } public override long Position { get { return Seek(0, SeekOrigin.Current); } set { Seek(value, SeekOrigin.Begin); } } public override int Read(byte[] buffer, int offset, int count) { if (stream == null) throw new ObjectDisposedException("Invalid stream object."); //if (offset != 0) //{ // throw new NotSupportedException("Only 0 offset is supported"); //} IntPtr address = IntPtr.Zero; stream.Read(buffer, count, ref address); int bytesRead = address.ToInt32(); //unsafe //{ // IntPtr address = new IntPtr(&bytesRead); // stream.Read(buffer, count, address); //} return bytesRead; } //public long Read(byte[] buffer, int offset, int count) //{ // IntPtr address = IntPtr.Zero; // stream.Read(buffer, count, ref address); // long bytesRead = address.ToInt64(); // return bytesRead; //} public override long Seek(long offset, SeekOrigin origin) { if (stream == null) throw new ObjectDisposedException("Invalid stream object."); IntPtr address = IntPtr.Zero; stream.Seek(offset, (int)origin, ref address); long position = address.ToInt64(); //long position = 0; //unsafe //{ // IntPtr address = new IntPtr(&position); // stream.Seek(offset, (int)origin, address); //} return position; } public override void SetLength(long value) { if (stream == null) throw new ObjectDisposedException("Invalid stream object."); stream.SetSize(value); } public override void Write(byte[] buffer, int offset, int count) { if (stream == null) throw new ObjectDisposedException("Invalid stream object."); //if (offset != 0) //{ // throw new NotSupportedException("Only 0 offset is supported"); //} //stream.Write(buffer, count,ref IntPtr.Zero); stream.Write(buffer, count, ref PWrite); stream.Commit(0); } public void WriteBytes(byte[] buffer) { if (stream == null) throw new ObjectDisposedException("Invalid stream object."); int count = 0; if (buffer == null) return; count = buffer.Length; //stream.Write(buffer, count,ref IntPtr.Zero); stream.Write(buffer, count, ref PWrite); stream.Commit(0); } //Convenience method for writing Strings to the stream public void Write(string s) { System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding(); byte[] pv = encoding.GetBytes(s); Write(pv, 0, pv.GetLength(0)); } public override void Close() { try { if (this.stream != null) stream.Commit(0); } finally { this.Dispose(); //GC.SuppressFinalize(this); } } } }