Incorrect breaking #import behavior in recent (e.g. 16.6.2) MSVC versions

Yesterday’s bug is not the only “news”. Some time ago I already saw weird broken behavior of rebuild of DirectShowSpy.dll with current version of Visual Studio and MSVC.

Now the problem is getting more clear.

Here is some interface:

[
    object,
    uuid(6CE45967-F228-4F7B-8B93-83DC599618CA),
    //dual,
    //oleautomation,
    nonextensible,
    pointer_default(unique)
]
interface IMuxFilter : IUnknown
{
    HRESULT IsTemporaryIndexFileEnabled();
    HRESULT SetTemporaryIndexFileEnabled([in] BOOL bTemporaryIndexFileEnabled);
    HRESULT GetAlignTrackStartTimeDisabled();
    HRESULT SetAlignTrackStartTimeDisabled([in] BOOL bAlignTrackStartTimeDisabled);
    HRESULT GetMinimalMovieDuration([out] LONGLONG* pnMinimalMovieDuration);
    HRESULT SetMinimalMovieDuration([in] LONGLONG nMinimalMovieDuration);
};

Compiled into type library it looks okay. Windows SDK 10.0.18362 COM/OLE Object Viewer shows the correct definition obtained from the type library:

[
    odl,
    uuid(6CE45967-F228-4F7B-8B93-83DC599618CA),
    nonextensible
]
interface IMuxFilter : IUnknown {
    HRESULT _stdcall IsTemporaryIndexFileEnabled();
    HRESULT _stdcall SetTemporaryIndexFileEnabled([in] long bTemporaryIndexFileEnabled);
    HRESULT _stdcall GetAlignTrackStartTimeDisabled();
    HRESULT _stdcall SetAlignTrackStartTimeDisabled([in] long bAlignTrackStartTimeDisabled);
    HRESULT _stdcall GetMinimalMovieDuration([out] int64* pnMinimalMovieDuration);
    HRESULT _stdcall SetMinimalMovieDuration([in] int64 nMinimalMovieDuration);
};

Now what happens when MSVC #import takes it into Win32 32-bit code:

struct __declspec(uuid("6ce45967-f228-4f7b-8b93-83dc599618ca"))
IMuxFilter : IUnknown
{
    //
    // Raw methods provided by interface
    //

      virtual HRESULT __stdcall IsTemporaryIndexFileEnabled ( ) = 0;
    virtual HRESULT _VtblGapPlaceholder1( ) { return E_NOTIMPL; }
      virtual HRESULT __stdcall SetTemporaryIndexFileEnabled (
        /*[in]*/ long bTemporaryIndexFileEnabled ) = 0;
    virtual HRESULT _VtblGapPlaceholder2( ) { return E_NOTIMPL; }
      virtual HRESULT __stdcall GetAlignTrackStartTimeDisabled ( ) = 0;
    virtual HRESULT _VtblGapPlaceholder3( ) { return E_NOTIMPL; }
      virtual HRESULT __stdcall SetAlignTrackStartTimeDisabled (
        /*[in]*/ long bAlignTrackStartTimeDisabled ) = 0;
    virtual HRESULT _VtblGapPlaceholder4( ) { return E_NOTIMPL; }
      virtual HRESULT __stdcall GetMinimalMovieDuration (
        /*[out]*/ __int64 * pnMinimalMovieDuration ) = 0;
    virtual HRESULT _VtblGapPlaceholder5( ) { return E_NOTIMPL; }
      virtual HRESULT __stdcall SetMinimalMovieDuration (
        /*[in]*/ __int64 nMinimalMovieDuration ) = 0;
    virtual HRESULT _VtblGapPlaceholder6( ) { return E_NOTIMPL; }
};

WTF _VtblGapPlaceholder1??? That was uncalled for!

It looks like some 32/64 bullshit added by MSVC from some point (cross-compilation issue?) for no good reason reason. A sort of gentle reminder that one should get rid of #import in C++ code.

Please have it fixed, 32-bit code is something still being used.

#import of Microsoft’s own quartz.dll, for example, has the same invalid gap insertion:

struct __declspec(uuid("56a868bc-0ad4-11ce-b03a-0020af0ba770"))
IMediaTypeInfo : IDispatch
{
    //
    // Raw methods provided by interface
    //

      virtual HRESULT __stdcall get_Type (
        /*[out,retval]*/ BSTR * strType ) = 0;
    virtual HRESULT _VtblGapPlaceholder1( ) { return E_NOTIMPL; }
      virtual HRESULT __stdcall get_Subtype (
        /*[out,retval]*/ BSTR * strType ) = 0;
    virtual HRESULT _VtblGapPlaceholder2( ) { return E_NOTIMPL; }
};

Leave a Reply