Marshalling an LPSTREAM back to Managed code...

K

Kevin Derhak

Hi:

I have a C# application that is required to call into an unmanged c++
dll and retrieve an LPSTREAM. Next I need to be able to use this
LPSTREAM inside of a class that I created to wrap the
System.Runtime.InteropServices.ComTypes.IStream interface. This code
is based on a sample I found while researching this issue.

My problem is I can't get the stream back into managed code without an
exception being thrown from an invalid cast or an internal component
threw an exception.

If anyone could shed some light, point me to some excplict help or
code I would gladly donate an organ.

My sample code is below.

unmanaged:

__declspec(dllexport) UINT vsGetAnyStream(LPSTREAM &pStream )
{
CoInitialize(NULL) ;

HRESULT hr = S_OK ;
CString csPath = _T("E:\\WorkBackup\\Test100.msg") ;

try
{
_IMemoryStreamPtr FileStream = NULL ;
hr = SHCreateStreamOnFileEx(csPath, STGM_SHARE_DENY_NONE|
STGM_READWRITE|STGM_FAILIFTHERE , FILE_ATTRIBUTE_NORMAL, FALSE,NULL,
(LPSTREAM*)&pStream ) ;
//if ( SUCCEEDED(hr) )
// memStream = FileStream ;
}
catch( CException *pEx )
{
TCHAR szBuffer[MAX_ERRROR_MESSAGE_SIZE] ;
pEx->GetErrorMessage(szBuffer, MAX_ERRROR_MESSAGE_SIZE ) ;
OutputDebugString( szBuffer ) ;
return E_UNEXPECTED ;
}

return hr ;
}


Unmanged:

Sample invocation...

Object obj = new Object();
uint uResult = GetAnyStream( out obj );
MyMemoryStream Content =
(MyMemoryStream)Marshal.CreateWrapperOfType(obj,typeof(MyMemoryStream)) ;



[DllImport("MyDLL.dll", CallingConvention = CallingConvention.Cdecl,
SetLastError = true, EntryPoint = "vsGetAnyStream", CharSet =
CharSet.Auto)]
public static extern uint
GetAnyStream([MarshalAs(UnmanagedType.Interface)] out Object
stream );

MemoryStream class
[ClassInterface(ClassInterfaceType.AutoDispatch)]
[ComVisibleAttribute(true)]
public class MyMemoryStream : MemoryStream,
System.Runtime.InteropServices.ComTypes.IStream
{

public MyMemoryStream()
: base()
{

}

public MyMemoryStream(IntPtr ptr2Stream)
{

}

public MyMemoryStream(int Capacity)
: base(Capacity)
{

}

public void ReadBuffer(Int32 iStreamPtr, int iByteCount)
{
try
{

byte[] buffer = new byte[iByteCount];

for (int iOffset = 0; iOffset < iByteCount; iOffset++)
buffer[iOffset] =
Marshal.ReadByte((IntPtr)iStreamPtr, (Int32)iOffset);

Read(buffer, 0, iByteCount);
}
catch (Exception ex)
{
Console.WriteLine("ReadBuffer failed for the following
reason: " + ex.Message);
}

}

/// <summary>
/// Write
///
/// </summary>
/// <param name="iStreamPtr"></param>
/// <param name="iByteCount"></param>
public void Write(Int32 iStreamPtr, int iByteCount)
{
try
{

byte[] buffer = new byte[iByteCount];
for (int iOffset = 0; iOffset < iByteCount; iOffset++)
buffer[iOffset] = Marshal.ReadByte((IntPtr)
(iStreamPtr), (Int32)iOffset);

Write(buffer, 0, iByteCount);
}
catch (Exception ex)
{
Console.WriteLine("Write failed for the following
reason: " + ex.Message);
}
}


public void WriteBuffer(Int32 iStreamPtr, int iByteCount)
{
byte[] buffer = new byte[iByteCount];
for (int iOffset = 0; iOffset < iByteCount; iOffset++)
buffer[iOffset] = Marshal.ReadByte((IntPtr)
(iStreamPtr), (Int32)iOffset);

Write(buffer, 0, iByteCount);
base.Seek(0, (SeekOrigin)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));
}

// Implementation of the IStream interface
public void Clone(out
System.Runtime.InteropServices.ComTypes.IStream ppstm)
{
ppstm = null;
}

public void Read(byte[] pv, int cb, System.IntPtr pcbRead)
{
long bytesRead = Read(pv, 0, cb);
if (pcbRead != IntPtr.Zero) Marshal.WriteInt64(pcbRead,
bytesRead);
}

public void Write(byte[] pv, int cb, System.IntPtr pcbWritten)
{
Write(pv, 0, cb);
if (pcbWritten != IntPtr.Zero)
Marshal.WriteInt64(pcbWritten, (Int64)cb);
}

public void Write(IntPtr pStream)
{
byte[] byteArray = new byte[54000];

Object obj = Marshal.GetObjectForIUnknown(pStream);
String s = obj.GetType().ToString();
IMemoryStream mem = (IMemoryStream)obj;

System.Runtime.InteropServices.ComTypes.STATSTG pstatstg;

mem.Stat(out pstatstg, 0);
}

public void Seek(long dlibMove, int dwOrigin, System.IntPtr
plibNewPosition)
{
long pos = base.Seek(dlibMove, (SeekOrigin)dwOrigin);
if (plibNewPosition != IntPtr.Zero)
Marshal.WriteInt64(plibNewPosition, pos);
}

public void SetSize(long libNewSize) { }

public void
CopyTo(System.Runtime.InteropServices.ComTypes.IStream pstm, long cb,
System.IntPtr pcbRead, System.IntPtr pcbWritten)
{
}

public void Commit(int grfCommitFlags) { }

public void LockRegion(long libOffset, long cb, int
dwLockType) { }

public void Revert() { }

public void UnlockRegion(long libOffset, long cb, int
dwLockType) { }

public void Stat(out
System.Runtime.InteropServices.ComTypes.STATSTG pstatstg, int
grfStatFlag)
{
pstatstg = new
System.Runtime.InteropServices.ComTypes.STATSTG();
}

}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top