-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathComStream.cs
129 lines (111 loc) · 3.48 KB
/
ComStream.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using STATSTG = System.Runtime.InteropServices.ComTypes.STATSTG;
namespace IDataObjectViewer
{
class ComStream : Stream
{
private readonly IStream _stream;
private readonly bool _autoRelease;
private readonly bool _readOnly;
public IStream BaseStream => _stream;
#region Stream
/// <summary>
/// Initialize ComStream Object
/// </summary>
/// <param name="istream"></param>
/// <param name="autoReleaseAsComObject"></param>
public ComStream(IStream istream, bool autoReleaseAsComObject = false, bool asReadOnly = false)
{
_stream = istream;
_autoRelease = autoReleaseAsComObject;
_readOnly = asReadOnly;
}
public override void Flush()
{
this._stream.Commit(0);
}
public override long Seek(long offset, SeekOrigin origin)
{
long pos;
_stream.Seek(offset, origin, out pos);
return pos;
}
public override void SetLength(long value)
{
if (_readOnly) throw new NotSupportedException();
_stream.SetSize(value);
}
public override int Read(byte[] buffer, int offset, int count)
{
uint read;
if (offset != 0) throw new NotImplementedException();
_stream.Read(buffer, count, out read);
return (int) read;
}
public override void Write(byte[] buffer, int offset, int count)
{
if(_readOnly)throw new NotSupportedException();
if (offset != 0) throw new NotImplementedException();
_stream.Write(buffer, count, IntPtr.Zero);
}
public override bool CanRead => true;
public override bool CanSeek => true;
public override bool CanWrite
{
get
{
if (_readOnly) return false;
STATSTG statstg;
_stream.Stat(out statstg, STATFLAG.NONAME);
// STGM_READ = 1 or STGM_READWRITE = 2
return (statstg.grfMode & 0x3) != 0;
}
}
public override long Length
{
get
{
STATSTG statstg;
_stream.Stat(out statstg, STATFLAG.NONAME);
// STGM_READ = 1 or STGM_READWRITE = 2
return statstg.cbSize;
}
}
public override long Position
{
get { return this.Seek(0, SeekOrigin.Current); }
set { this.Seek(0, SeekOrigin.Begin); }
}
#endregion Stream
#region Dispose
public event EventHandler Disposed;
private bool disposed = false;
protected override void Dispose(bool disposing)
{
try
{
if (!disposed)
{
disposed = true;
Disposed?.Invoke(this,new EventArgs());
if (_autoRelease) Marshal.ReleaseComObject(_stream);
if (disposing)
{
GC.SuppressFinalize(this);
}
}
}
finally
{
base.Dispose(disposing);
}
}
#endregion Dispose
}
}