R
Ralf
Hallo,
I'm trying to call a COM function from C#.
The function has a parameter from the type array of IStream* (IStream**).
The COM component (out-proc-server (.exe)) has the following code:
(C++)
STDMETHODIMP CIntf::SendFiles(int noOfStreams, IUnknown** dataStreams)
{
for(int i = 0; i < noOfStreams; i++)
{
if(*(dataStreams + i))
{
IStream* iStream;
hr = (*(dataStreams + i))->QueryInterface(IID_IStream,
(void**)&iStream);
... ...
}
}
}
I can't change the code of the COM component.
If I'm calling the function from C# I get an E_NOINTERFACE error from
QueryInterface in the COM component.
Does anyone has an idea about the problem in my C# code?
I asked the same in the german newsgroup, but I got no answer. I hope you
are better here.
Best reguards
Ralf Beckers
(C#)
public void SendFiles(string file)
{
FileStream fs = new FileStream(file, FileMode.Open);
StreamReader sr = new StreamReader(fs, Encoding.Default);
string trc = sr.ReadToEnd();
sr.Close();
fs.Close();
byte[] data = Encoding.Default.GetBytes(trc);
IStorage storage;
ComTypes.IStream stream;
int err = StgCreateDocfile(null,
STGM.CREATE | STGM.READWRITE | STGM.TRANSACTED |
STGM.SHARE_EXCLUSIVE | STGM.DELETEONRELEASE,
0, out storage);
storage.CreateStream("TRTFiles.trt", (uint)(STGM.READWRITE |
STGM.SHARE_EXCLUSIVE), 0,0, out stream);
stream.Write(data, data.Length, IntPtr.Zero);
stream.Commit((int)STGC.OVERWRITE);
storage.Commit((int)STGC.OVERWRITE);
IntPtr ptr = Marshal.GetIUnknownForObject(stream);
IntPtr[] arr = { ptr };
IntPtr buffer = Marshal.AllocCoTaskMem( Marshal.SizeOf( typeof(IntPtr ))
* arr.Length );
Marshal.Copy(arr, 0, buffer, arr.Length );
object obj = buffer;
this.intf.SendFiles(1, ref obj);
Marshal.FreeCoTaskMem((IntPtr)buffer);
}
[DllImport("ole32.dll")]
static extern int StgCreateDocfile([MarshalAs(UnmanagedType.LPWStr)]string
pwcsName, STGM grfMode, uint reserved, out IStorage ppstgOpen);
[Flags]
public enum CSMFlags : short
{
NONE = 0,
EVENT_EN = 0x0100,
POLLED_EVENTS = 0x0001
}
[Flags]
public enum CSMFilterType : byte
{
ENABLE_MSG = 0x00,
BLOCK_MSG = 0x01,
NO_FILTER = 0x02
}
[Flags]
internal enum STGC : int
{
DEFAULT = 0,
OVERWRITE = 1,
ONLYIFCURRENT = 2,
DANGEROUSLYCOMMITMERELYTODISKCACHE = 4,
CONSOLIDATE = 8
}
[Flags]
internal enum STGM : int
{
DIRECT = 0x00000000,
TRANSACTED = 0x00010000,
SIMPLE = 0x08000000,
READ = 0x00000000,
WRITE = 0x00000001,
READWRITE = 0x00000002,
SHARE_DENY_NONE = 0x00000040,
SHARE_DENY_READ = 0x00000030,
SHARE_DENY_WRITE= 0x00000020,
SHARE_EXCLUSIVE = 0x00000010,
PRIORITY = 0x00040000,
DELETEONRELEASE = 0x04000000,
NOSCRATCH = 0x00100000,
CREATE = 0x00001000,
CONVERT = 0x00020000,
FAILIFTHERE = 0x00000000,
NOSNAPSHOT = 0x00200000,
DIRECT_SWMR = 0x00400000
}
[ComImport]
[Guid("0000000b-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IStorage
{
void CreateStream(
/* [string][in] */ string pwcsName,
/* [in] */ uint grfMode,
/* [in] */ uint reserved1,
/* [in] */ uint reserved2,
/* [out] */ out ComTypes.IStream ppstm);
void OpenStream(
/* [string][in] */ string pwcsName,
/* [unique][in] */ IntPtr reserved1,
/* [in] */ uint grfMode,
/* [in] */ uint reserved2,
/* [out] */ out ComTypes.IStream ppstm);
void CreateStorage(
/* [string][in] */ string pwcsName,
/* [in] */ uint grfMode,
/* [in] */ uint reserved1,
/* [in] */ uint reserved2,
/* [out] */ out IStorage ppstg);
void OpenStorage(
/* [string][unique][in] */ string pwcsName,
/* [unique][in] */ IStorage pstgPriority,
/* [in] */ uint grfMode,
/* [unique][in] */ IntPtr snbExclude,
/* [in] */ uint reserved,
/* [out] */ out IStorage ppstg);
void CopyTo(
/* [in] */ uint ciidExclude,
/* [size_is][unique][in] */ Guid rgiidExclude, // should this be an array?
/* [unique][in] */ IntPtr snbExclude,
/* [unique][in] */ IStorage pstgDest);
void MoveElementTo(
/* [string][in] */ string pwcsName,
/* [unique][in] */ IStorage pstgDest,
/* [string][in] */ string pwcsNewName,
/* [in] */ uint grfFlags);
void Commit(
/* [in] */ uint grfCommitFlags);
void Revert();
void EnumElements(
/* [in] */ uint reserved1,
/* [size_is][unique][in] */ IntPtr reserved2,
/* [in] */ uint reserved3,
/* [out] */ out IEnumSTATSTG ppenum);
void DestroyElement(
/* [string][in] */ string pwcsName);
void RenameElement(
/* [string][in] */ string pwcsOldName,
/* [string][in] */ string pwcsNewName);
void SetElementTimes(
/* [string][unique][in] */ string pwcsName,
/* [unique][in] */ ComTypes.FILETIME pctime,
/* [unique][in] */ ComTypes.FILETIME patime,
/* [unique][in] */ ComTypes.FILETIME pmtime);
void SetClass(
/* [in] */ Guid clsid);
void SetStateBits(
/* [in] */ uint grfStateBits,
/* [in] */ uint grfMask);
void Stat(
/* [out] */ out ComTypes.STATSTG pstatstg,
/* [in] */ uint grfStatFlag);
}
[ComImport]
[Guid("0000000d-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IEnumSTATSTG
{
// The user needs to allocate an STATSTG array whose size is celt.
[PreserveSig]
uint
Next(
uint celt,
[MarshalAs(UnmanagedType.LPArray), Out]
ComTypes.STATSTG[] rgelt,
out uint pceltFetched
);
void Skip(uint celt);
void Reset();
[return:MarshalAs(UnmanagedType.Interface)]
IEnumSTATSTG Clone();
}
I'm trying to call a COM function from C#.
The function has a parameter from the type array of IStream* (IStream**).
The COM component (out-proc-server (.exe)) has the following code:
(C++)
STDMETHODIMP CIntf::SendFiles(int noOfStreams, IUnknown** dataStreams)
{
for(int i = 0; i < noOfStreams; i++)
{
if(*(dataStreams + i))
{
IStream* iStream;
hr = (*(dataStreams + i))->QueryInterface(IID_IStream,
(void**)&iStream);
... ...
}
}
}
I can't change the code of the COM component.
If I'm calling the function from C# I get an E_NOINTERFACE error from
QueryInterface in the COM component.
Does anyone has an idea about the problem in my C# code?
I asked the same in the german newsgroup, but I got no answer. I hope you
are better here.
Best reguards
Ralf Beckers
(C#)
public void SendFiles(string file)
{
FileStream fs = new FileStream(file, FileMode.Open);
StreamReader sr = new StreamReader(fs, Encoding.Default);
string trc = sr.ReadToEnd();
sr.Close();
fs.Close();
byte[] data = Encoding.Default.GetBytes(trc);
IStorage storage;
ComTypes.IStream stream;
int err = StgCreateDocfile(null,
STGM.CREATE | STGM.READWRITE | STGM.TRANSACTED |
STGM.SHARE_EXCLUSIVE | STGM.DELETEONRELEASE,
0, out storage);
storage.CreateStream("TRTFiles.trt", (uint)(STGM.READWRITE |
STGM.SHARE_EXCLUSIVE), 0,0, out stream);
stream.Write(data, data.Length, IntPtr.Zero);
stream.Commit((int)STGC.OVERWRITE);
storage.Commit((int)STGC.OVERWRITE);
IntPtr ptr = Marshal.GetIUnknownForObject(stream);
IntPtr[] arr = { ptr };
IntPtr buffer = Marshal.AllocCoTaskMem( Marshal.SizeOf( typeof(IntPtr ))
* arr.Length );
Marshal.Copy(arr, 0, buffer, arr.Length );
object obj = buffer;
this.intf.SendFiles(1, ref obj);
Marshal.FreeCoTaskMem((IntPtr)buffer);
}
[DllImport("ole32.dll")]
static extern int StgCreateDocfile([MarshalAs(UnmanagedType.LPWStr)]string
pwcsName, STGM grfMode, uint reserved, out IStorage ppstgOpen);
[Flags]
public enum CSMFlags : short
{
NONE = 0,
EVENT_EN = 0x0100,
POLLED_EVENTS = 0x0001
}
[Flags]
public enum CSMFilterType : byte
{
ENABLE_MSG = 0x00,
BLOCK_MSG = 0x01,
NO_FILTER = 0x02
}
[Flags]
internal enum STGC : int
{
DEFAULT = 0,
OVERWRITE = 1,
ONLYIFCURRENT = 2,
DANGEROUSLYCOMMITMERELYTODISKCACHE = 4,
CONSOLIDATE = 8
}
[Flags]
internal enum STGM : int
{
DIRECT = 0x00000000,
TRANSACTED = 0x00010000,
SIMPLE = 0x08000000,
READ = 0x00000000,
WRITE = 0x00000001,
READWRITE = 0x00000002,
SHARE_DENY_NONE = 0x00000040,
SHARE_DENY_READ = 0x00000030,
SHARE_DENY_WRITE= 0x00000020,
SHARE_EXCLUSIVE = 0x00000010,
PRIORITY = 0x00040000,
DELETEONRELEASE = 0x04000000,
NOSCRATCH = 0x00100000,
CREATE = 0x00001000,
CONVERT = 0x00020000,
FAILIFTHERE = 0x00000000,
NOSNAPSHOT = 0x00200000,
DIRECT_SWMR = 0x00400000
}
[ComImport]
[Guid("0000000b-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IStorage
{
void CreateStream(
/* [string][in] */ string pwcsName,
/* [in] */ uint grfMode,
/* [in] */ uint reserved1,
/* [in] */ uint reserved2,
/* [out] */ out ComTypes.IStream ppstm);
void OpenStream(
/* [string][in] */ string pwcsName,
/* [unique][in] */ IntPtr reserved1,
/* [in] */ uint grfMode,
/* [in] */ uint reserved2,
/* [out] */ out ComTypes.IStream ppstm);
void CreateStorage(
/* [string][in] */ string pwcsName,
/* [in] */ uint grfMode,
/* [in] */ uint reserved1,
/* [in] */ uint reserved2,
/* [out] */ out IStorage ppstg);
void OpenStorage(
/* [string][unique][in] */ string pwcsName,
/* [unique][in] */ IStorage pstgPriority,
/* [in] */ uint grfMode,
/* [unique][in] */ IntPtr snbExclude,
/* [in] */ uint reserved,
/* [out] */ out IStorage ppstg);
void CopyTo(
/* [in] */ uint ciidExclude,
/* [size_is][unique][in] */ Guid rgiidExclude, // should this be an array?
/* [unique][in] */ IntPtr snbExclude,
/* [unique][in] */ IStorage pstgDest);
void MoveElementTo(
/* [string][in] */ string pwcsName,
/* [unique][in] */ IStorage pstgDest,
/* [string][in] */ string pwcsNewName,
/* [in] */ uint grfFlags);
void Commit(
/* [in] */ uint grfCommitFlags);
void Revert();
void EnumElements(
/* [in] */ uint reserved1,
/* [size_is][unique][in] */ IntPtr reserved2,
/* [in] */ uint reserved3,
/* [out] */ out IEnumSTATSTG ppenum);
void DestroyElement(
/* [string][in] */ string pwcsName);
void RenameElement(
/* [string][in] */ string pwcsOldName,
/* [string][in] */ string pwcsNewName);
void SetElementTimes(
/* [string][unique][in] */ string pwcsName,
/* [unique][in] */ ComTypes.FILETIME pctime,
/* [unique][in] */ ComTypes.FILETIME patime,
/* [unique][in] */ ComTypes.FILETIME pmtime);
void SetClass(
/* [in] */ Guid clsid);
void SetStateBits(
/* [in] */ uint grfStateBits,
/* [in] */ uint grfMask);
void Stat(
/* [out] */ out ComTypes.STATSTG pstatstg,
/* [in] */ uint grfStatFlag);
}
[ComImport]
[Guid("0000000d-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IEnumSTATSTG
{
// The user needs to allocate an STATSTG array whose size is celt.
[PreserveSig]
uint
Next(
uint celt,
[MarshalAs(UnmanagedType.LPArray), Out]
ComTypes.STATSTG[] rgelt,
out uint pceltFetched
);
void Skip(uint celt);
void Reset();
[return:MarshalAs(UnmanagedType.Interface)]
IEnumSTATSTG Clone();
}