tags:

views:

141

answers:

1

I have a legacy COM control (Core) that accepts an IUnknown to a sink. The purpose is to allow the Core to read/write data through this sink interface. The Core/Sink pointers are currently in use in legacy systems and are not easily modified.

The problem I'm having is when I attempt to call the Core from managed code and pass in an object that (attempts) to implement the sink in managed code. I've debugged the Core to the point that it is preparing to call the sink. Prior (not after) the call, I get a message akin to:

"Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call..."

I've seen and worked through these in pure legacy code, but the introduction of managed code has me perplexed.

Here are the smallest representations of the two interfaces that I believe are neccessary.

interface ICore : IDispatch { [id(1), helpstring("method Init")] HRESULT Init([in] IUnknown *pDataManSink);

HRESULT FireOnImport([in] LPCOLESTR pszFormName, [in] LPCOLESTR pszTagName, [in] VARIANT pszData);

... more methods }

Data access "sink" as from the IDL (reduced for ease problem demonstration)

interface IDataManagerSinkEx : IUnknown
{
   [helpstring("method ReadData")] HRESULT ReadData([in] LPCTSTR pszDataKey, [out, retval] BSTR* pbsData);
   [helpstring("method WriteData")] HRESULT WriteData([in] LPCTSTR pszDataKey, [in] LPCTSTR pszData);
   [helpstring("method ReadDataEx")] HRESULT ReadTagEx([in] LPCTSTR pszDataKey, [out] short *pwExtraInfoOut, [out, retval] BSTR *pbsData);
   [helpstring("method WriteDataEx")] HRESULT WriteTagEx([in] LPCTSTR pszDataKey, [in] short wExtraInfo, [in] LPCTSTR pszData);
}

I've tried a variety of implmentation of the sink in C#, to no avail or change in error condictions. Here is the most current implementation, and yes, I hand coded the interface definition, as using the one from the type lib did not work. (same issue)

Thanks.

[ComImport]
[Guid( "AB79770E-8143-45E6-B082-E985E6DFA5CB" )]
[InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]
public interface IMyDataManagerSinkEx
{
  [PreserveSig]
  int ReadData( [MarshalAs( UnmanagedType.LPStr )]string pszDataKey, out string data );

  [PreserveSig]
  int WriteTag( [MarshalAs( UnmanagedType.LPStr )]string pszDataKey, [MarshalAs( UnmanagedType.LPStr )]string pszData );

  [PreserveSig]
  int ReadTagEx( [MarshalAs( UnmanagedType.LPStr )]string pszDataKey, out short pwExraInfoOut, out string dataOut );

  [PreserveSig]
  int WriteTagEx( [MarshalAs( UnmanagedType.LPStr )]string pszDataKey, short wExtraInfo, [MarshalAs( UnmanagedType.LPStr )]string pszData );
}

class public SinkImpl : IMyDataManagerSinkEx
{
  [PreserveSig]
  public int ReadData( [MarshalAs( UnmanagedType.LPStr )]string pszDataKey, out string data )
  {
     throw new NotImplementedException();
  }

  [PreserveSig]
  public int WriteTag( [MarshalAs( UnmanagedType.LPStr )]string pszDataKey, [MarshalAs( UnmanagedType.LPStr )]string pszData )
  {
     throw new NotImplementedException();
  }

  [PreserveSig]
  public int ReadTagEx( [MarshalAs( UnmanagedType.LPStr )]string pszDataKey, out short pwExraInfoOut, out string dataOut )
  {
     throw new NotImplementedException();
  }

  [PreserveSig]
  public int WriteTagEx( [MarshalAs( UnmanagedType.LPStr )]string pszDataKey, short wExtraInfo, [MarshalAs( UnmanagedType.LPStr )]string pszData )
  {
     throw new NotImplementedException();
  }
}
A: 

That ESP problem usually means that you have some sort of mix up between the runtime libraries of your DLLs. For instance in our code base there are a lot of COM objects, if the current COM registration of some of these objects are from the debug build but others the registration is of the release versions then you will get the ESP error when methods are called on the interfaces that these objects provide.

I have a script that registers all the known COM objects that are in our codebase.

Stone Free