Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Reflection
Imports System.Runtime.InteropServices
Imports System.Runtime.InteropServices.ComTypes
Imports System.Security.Cryptography
Imports System.IO
Imports System.Diagnostics

Public Class VirtualFileStream
    Implements IStream

    Private _MemoryStream As MemoryStream
    Private _Position As Integer = 0

    Public Sub New(ByVal MemoryStream As MemoryStream)
        _MemoryStream = MemoryStream
    End Sub

    Sub Read(ByVal pv() As Byte, ByVal cb As Integer, ByVal pcbRead As System.IntPtr) Implements IStream.Read
        Dim ReadBytes As Integer

        If _Position < 0 Or _Position > _MemoryStream.Length Then
            ReadBytes = 0
        Else
            ' Lock memory stream to be able for all instances set required position within memory stream
            SyncLock (_MemoryStream)
                _MemoryStream.Position = _Position
                ReadBytes = _MemoryStream.Read(pv, 0, cb)
            End SyncLock
        End If

        If IntPtr.Zero <> pcbRead Then Marshal.WriteIntPtr(pcbRead, New IntPtr(ReadBytes))
    End Sub

    Sub Write(ByVal pv() As Byte, ByVal cb As Integer, ByVal pcbWritten As System.IntPtr) Implements IStream.Write
        Throw New Exception("The method or operation is not implemented.")
    End Sub

    Sub Clone(ByRef ppstm As System.Runtime.InteropServices.ComTypes.IStream) Implements IStream.Clone
        ppstm = New VirtualFileStream(_MemoryStream)
    End Sub

    Sub Seek(ByVal dlibMove As Long, ByVal dwOrigin As Integer, ByVal plibNewPosition As System.IntPtr) Implements IStream.Seek
        Dim Origin As SeekOrigin = CType(dwOrigin, SeekOrigin)

        ' Let's protect _Position: _Position might be changed by Read()
        SyncLock (_MemoryStream)
            Select Case Origin
                Case SeekOrigin.Begin
                    _Position = dlibMove
                Case SeekOrigin.Current
                    _Position = _Position + dlibMove
                Case SeekOrigin.End
                    _Position = _MemoryStream.Length + dlibMove
            End Select
        End SyncLock

        If IntPtr.Zero <> plibNewPosition Then Marshal.WriteInt64(plibNewPosition, _Position)
    End Sub

    Sub Stat(ByRef pstatstg As System.Runtime.InteropServices.ComTypes.STATSTG, ByVal grfStatFlag As Integer) Implements IStream.Stat
        pstatstg = New System.Runtime.InteropServices.ComTypes.STATSTG
        pstatstg.cbSize = _MemoryStream.Length
    End Sub

    Sub Commit(ByVal grfCommitFlags As Integer) Implements IStream.Commit
        Throw New Exception("The method or operation is not implemented.")
    End Sub

    Sub CopyTo(ByVal pstm As System.Runtime.InteropServices.ComTypes.IStream, ByVal cb As Long, ByVal pcbRead As System.IntPtr, ByVal pcbWritten As System.IntPtr) Implements IStream.CopyTo
        Throw New Exception("The method or operation is not implemented.")
    End Sub

    Sub LockRegion(ByVal libOffset As Long, ByVal cb As Long, ByVal dwLockType As Integer) Implements IStream.LockRegion
        Throw New Exception("The method or operation is not implemented.")
    End Sub

    Sub Revert() Implements IStream.Revert
        Throw New Exception("The method or operation is not implemented.")
    End Sub

    Sub SetSize(ByVal libNewSize As Long) Implements IStream.SetSize
        Throw New Exception("The method or operation is not implemented.")
    End Sub

    Sub UnlockRegion(ByVal libOffset As Long, ByVal cb As Long, ByVal dwLockType As Integer) Implements IStream.UnlockRegion
        Throw New Exception("The method or operation is not implemented.")
    End Sub
End Class
