views:

218

answers:

1

Hey folks, I've been stuck on this for the past few days. I have a custom COM interface that I am able to cast to, but when I call one if it's functions I get an AccessViolationException because the this pointer has changed.

The below code represents the two interfaces that I am marshalling. All methods result in the same problem.

Any help will be greatly appreciated.

/*
    struct SourceConfig {       
        LONGLONG                            llBufferDuration;           // The buffer duration to use while receiving samples from the network, measured in 100nsec units
        REFERENCE_TIME                      rtStartTime;
        FLOAT                               fRate;                      // Negative: rewind, Positive: forward
        BYTE                                btConnectionTimeout;        // The time to wait for a connection to be established, measured in seconds
        BOOL                                bKeyFramesOnly;
        CHAR                                pIP[128];
        WORD                                wPort;
        CHAR                                pChannel[64];
        BYTE                                pbtCertificate[96];
        SAMPLE_TIME                         eSampleTime;// Indicates weather to directly route the samples with the absolute UTC 
                                                        // time OR to make all generated samples relative to zero, default value
                                                        // is 'RELATIVE'.
        HANDLE                              hEvent;                     // Used to wait for the operation completion ( optional )
        BYTE                                bAutoSeekToNextAvailPos;    // If seeking into a hole automatically resume streaming from the next available position
        DWORD                               dwSampleStarvationTimeout;  // The maximal amount of seconds ( and not msec ) the filter might wait for incoming data
    };


    interface
    __declspec(uuid("{9331DC40-40F5-438a-B9C0-44B479246C98}"))
    IStreamingSourceCallback : IUnknown {
        virtual STDMETHODIMP OnStreamingSourceEvent(IN STREAMING_SRC_EVENT eCode, IN const VARIANT* pvar1 = 0, IN const VARIANT* pvar2 = 0, IN const VARIANT* pvar3 = 0) = 0;
    };

    interface
    __declspec(uuid("{ECF7715E-E973-4bb9-AEED-389845F0E297}"))
    IStreamingSource : IUnknown {
        virtual HRESULT GetConfig(OUT SourceConfig* pCfg) = 0;
        virtual HRESULT SetConfig(IN const SourceConfig* pCfg) = 0;
        virtual HRESULT SetCallback(IN IStreamingSourceCallback* pCallback) = 0;
        virtual HRESULT UpdateAbsoluteRefTime(IN LONGLONG& llRefTime) = 0;

        virtual HRESULT GetSeekPos(IN OUT REFERENCE_TIME& rtSeek) = 0;
    };

 */

public enum SAMPLE_TIME : byte
{
    Relative,
    Absolute
};

[StructLayout(LayoutKind.Sequential)]
public struct SourceConfig
{
    long BufferDuration;
    long StartTime;
    float Rate;
    byte ConnectionTimeout;
    [MarshalAs(UnmanagedType.Bool)]
    bool KeyFramesOnly;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
    public string Ip;
    UInt16 Port;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
    public string Channel;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 96)]
    public byte[] Certificate;
    SAMPLE_TIME SampleTime;
    IntPtr Event;
    byte AutoSeekToNextAvailPos;
    uint SampleStarvationTimeout;
};

public enum STREAMING_SRC_EVENT : int
{
    SRC_NONE,
    SRC_CONNECTED,
    SRC_DISCONNECTED,
    SRC_ERROR,
    SRC_STARTTIME,
    SRC_STREAM_CLOSE2LIVE,
    SRC_STREAM_FAR_LIVE,
    SRC_NEARESTSEEK
};  

[ComImport, Guid("9331DC40-40F5-438a-B9C0-44B479246C98"), SuppressUnmanagedCodeSecurity, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IStreamingSourceCallback
{
    [PreserveSig]
    int OnStreamingSourceEvent(
        [In, MarshalAs(UnmanagedType.I4)] STREAMING_SRC_EVENT code,
        [In, MarshalAs(UnmanagedType.IUnknown)] object var1,
        [In, MarshalAs(UnmanagedType.IUnknown)] object var2,
        [In, MarshalAs(UnmanagedType.IUnknown)] object var3);
}

[ComImport, Guid("ECF7715E-E973-4bb9-AEED-389845F0E297"), SuppressUnmanagedCodeSecurity, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IStreamingSource
{
    [PreserveSig]
    int GetConfig([Out, MarshalAs(UnmanagedType.Struct)] out SourceConfig config);
    [PreserveSig]
    int SetConfig([In, MarshalAs(UnmanagedType.Struct)] SourceConfig config);
    [PreserveSig]
    int SetCallback([In, MarshalAs(UnmanagedType.Interface)] IStreamingSourceCallback callback);
    [PreserveSig]
    int UpdateAbsoluteRefTime([In, MarshalAs(UnmanagedType.I8)] ref long refTime);
    [PreserveSig]
    int GetSeekPos([In, Out, MarshalAs(UnmanagedType.I8)] ref long seekTime);
}

The following code shows the usage:

IStreamingSource ssInterface = vosFilter as IStreamingSource;
        if (ssInterface == null)
        {
            throw new ApplicationException("Could not get IStreamingSource. ");
        }

        if ((hr = ssInterface.SetCallback(_ssCallback)) < 0)
        {
            throw new ApplicationException("Could not set streaming source callback. " + DirectShowLib.DsError.GetErrorText(hr));
        }

ssInterface points to the right structure, as soon as stepping through to SetCallback, this points to garbage.

Thanks.

A: 

Do you still get the error if you take out the MarshalAs(UnmanagedType.Interface) on the IStreamingSourceCallback argument in your SetCallback method sig?

Jeremiah Morrill