Reputation: 49
I'm implementing drag and drop and clipboard copy/paste with CFSTR_FILEDESCRIPTOR and CFSTR_FILECONTENTS with IStream. So I implemented my own IStream where basically I map the stream to a .NET FileStream object.
But how do I know when to clean up my internal FileStream object?
I know COM calls IUnknown.Release() when it's finished with an object, but when I want to implement that, I also have to implement the rest of the IUnknown interface, while otherwise .NET handles it for me.
Can I have .NET call IDisposable.Dispose() when my COM object is released? Or is there a way to override the standard .NET IUnknown.Release() method?
This is my IStream adapter: (now I open and close the FileStream constantly)
Public Class StreamAdapter
Implements IStream
Private _filePath As String
Private _fileStream As FileStream
Private _position As Long = -1
Public Sub New(filePath As String)
_filePath = filePath
End Sub
Private Sub openStream()
If _fileStream Is Nothing Then
_fileStream = New FileStream(_filePath, FileMode.Open, FileAccess.Read)
If (_position = -1) Then
_fileStream.Seek(0, SeekOrigin.End)
Else
_fileStream.Seek(_position, SeekOrigin.Begin)
End If
End If
End Sub
Private Sub closeStream()
_position = _fileStream.Position
_fileStream.Dispose()
_fileStream = Nothing
End Sub
Public Sub Read(pv() As Byte, cb As Integer, pcbRead As IntPtr) Implements IStream.Read
openStream()
If _fileStream.Position + cb > _fileStream.Length Then
cb = _fileStream.Length - _fileStream.Position
End If
Dim bytesRead As Integer
If cb > 0 Then
bytesRead = _fileStream.Read(pv, 0, cb)
End If
If pcbRead <> IntPtr.Zero Then
Marshal.WriteInt32(pcbRead, bytesRead)
End If
closeStream()
End Sub
Public Sub Write(pv() As Byte, cb As Integer, pcbWritten As IntPtr) Implements IStream.Write
Throw New NotSupportedException()
End Sub
Public Sub Seek(dlibMove As Long, dwOrigin As Integer, plibNewPosition As IntPtr) Implements IStream.Seek
openStream()
Select Case dwOrigin
Case 0 ' STREAM_SEEK_SET
_fileStream.Seek(dlibMove, SeekOrigin.Begin)
Case 1 ' STREAM_SEEK_CUR
_fileStream.Seek(dlibMove, SeekOrigin.Current)
Case 2 ' STREAM_SEEK_END
_fileStream.Seek(dlibMove, SeekOrigin.End)
Case Else
Throw New NotSupportedException()
End Select
If plibNewPosition <> IntPtr.Zero Then
Marshal.WriteInt64(plibNewPosition, _fileStream.Position)
End If
closeStream()
End Sub
Public Sub SetSize(libNewSize As Long) Implements IStream.SetSize
Throw New NotSupportedException()
End Sub
Public Sub CopyTo(pstm As IStream, cb As Long, pcbRead As IntPtr, pcbWritten As IntPtr) Implements IStream.CopyTo
openStream()
If cb = -1 Then cb = Long.MaxValue
Dim endPosition As Long = Math.Min(_fileStream.Position + cb, _fileStream.Length)
Dim bytesRead As UInt64 = 0
Dim bytesWritten As UInt64 = 0
Dim ptrWritten As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(Of Integer))
While _fileStream.Position <> endPosition
cb = Math.Min(endPosition - _fileStream.Position, 1024 * 1000)
Dim pv(cb - 1) As Byte
bytesRead += _fileStream.Read(pv, 0, cb)
pstm.Write(pv, cb, ptrWritten)
bytesWritten += Marshal.ReadInt32(ptrWritten)
End While
pstm.Commit(0)
If Not IntPtr.Zero.Equals(pcbRead) Then
Marshal.WriteInt64(pcbRead, bytesRead)
End If
If Not IntPtr.Zero.Equals(pcbWritten) Then
Marshal.WriteInt64(pcbWritten, bytesWritten)
End If
closeStream()
End Sub
Public Sub Commit(grfCommitFlags As Integer) Implements IStream.Commit
Throw New NotSupportedException()
End Sub
Public Sub Revert() Implements IStream.Revert
Throw New NotSupportedException()
End Sub
Public Sub LockRegion(libOffset As Long, cb As Long, dwLockType As Integer) Implements IStream.LockRegion
Throw New NotSupportedException()
End Sub
Public Sub UnlockRegion(libOffset As Long, cb As Long, dwLockType As Integer) Implements IStream.UnlockRegion
Throw New NotSupportedException()
End Sub
Public Sub Stat(ByRef pstatstg As STATSTG, grfStatFlag As Integer) Implements IStream.Stat
openStream()
' Provide information about the stream
pstatstg.cbSize = _fileStream.Length
pstatstg.type = 2 ' STGTY_STREAM (Stream)
closeStream()
End Sub
Public Sub Clone(ByRef ppstm As IStream) Implements IStream.Clone
Throw New NotSupportedException()
End Sub
End Class
Upvotes: 0
Views: 43