I have a C# WPF application with a section that serves as an FTP client, listing files on a remote server and allowing the user to download them. I want the user to be able
I got the same issue, easy to fix though ;)
The problem is that we are creating a new memory stream whereas it is not needed since we already have ours. You can create in c# an Stream wrapper that implements IStream:
///
/// Simple class that exposes a read-only Stream as a IStream.
///
private class StreamWrapper : IStream
{
private Stream _stream;
public StreamWrapper(Stream stream)
{
_stream = stream;
}
public void Read(byte[] pv, int cb, System.IntPtr pcbRead)
{
Marshal.WriteInt32(pcbRead, _stream.Read(pv, 0, cb));
}
public void Seek(long dlibMove, int dwOrigin, System.IntPtr plibNewPosition)
{
Marshal.WriteInt32(plibNewPosition, (int)_stream.Seek(dlibMove, (SeekOrigin)dwOrigin));
}
public void Clone(out IStream ppstm)
{
throw new NotImplementedException();
}
public void Commit(int grfCommitFlags)
{
throw new NotImplementedException();
}
public void CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten)
{
throw new NotImplementedException();
}
public void LockRegion(long libOffset, long cb, int dwLockType)
{
throw new NotImplementedException();
}
public void Revert()
{
throw new NotImplementedException();
}
public void SetSize(long libNewSize)
{
throw new NotImplementedException();
}
public void Stat(out System.Runtime.InteropServices.ComTypes.STATSTG pstatstg, int grfStatFlag)
{
throw new NotImplementedException();
}
public void UnlockRegion(long libOffset, long cb, int dwLockType)
{
throw new NotImplementedException();
}
public void Write(byte[] pv, int cb, IntPtr pcbWritten)
{
throw new NotImplementedException();
}
}
And then in the VirtualFileDataObject class, change the signature of the SetData method so that you pass now a Stream:
public void SetData(short dataFormat, int index, Stream stream)
{
...
var iStream = new StreamWrapper(stream);
...
// Ensure the following line is commented out:
//Marshal.ReleaseComObject(iStream);
return new Tuple(ptr, NativeMethods.S_OK);
...
}
Now, no new memory stream will be created.
For further info, go to http://blogs.msdn.com/b/delay/archive/2009/11/04/creating-something-from-nothing-asynchronously-developer-friendly-virtual-file-implementation-for-net-improved.aspx#10496772 and read my comments