Why does UDT / struct with missing type information cause silent launch failure in vb6?

2

Consider this registered type library in a DLL:

[uuid(…), version(1.0)]
library structLib
{
    importlib("stdole2.tlb");

    [uuid(…)]
    typedef struct MyStruct
    {
        BSTR m_sStr;
    } MyStruct;
};

In vb6 I can reference this type library and use the UDT / struct in a compiled exe (simple form with a button), named a.exe:

Private Sub Command1_Click()

Dim obj As structLib.MyStruct

obj.m_sStr = "Hello"
MsgBox obj.m_sStr 

End Sub

When I remove the struct from the type library and recompile it, the previously compiled a.exe still works, even though the struct definition is no longer present. I assume this succeeds because the definition is embedded into the executable during the vb6 compilation process.

However, things work differently when I compile the following vb6 code against the unmodified type library (struct included) into a new executable, named b.exe:

Private Sub Command1_Click()

Dim obj As structLib.MyStruct

obj.m_sStr = "Hello"
MsgBox obj.m_sStr

Dim vt as Variant
vt = obj
MsgBox vt.m_sStr

End Sub

Notice the assignment of the struct to a Variant.

When I remove the struct definition from the type library once again, recompile it, and try to run the previously compiled b.exe, the program silently fails as the form won't even show up. At minimum, I expected

  • Starting the executable loads the form.
  • Clicking the button throws an error, due to assigning the struct with missing type information to the Variant.

For the record, I have tried to reproduce this behavior in C++:

structLib::MyStruct obj;
obj.m_sStr = SysAllocString(L"Hello");

MessageBox(GetActiveWindow(), obj.m_sStr, obj.m_sStr, MB_OK);

ATL::CComVariant vtRec;     
ATL::CComPtr<IRecordInfo> piRecInfo;            
HRESULT hr = GetRecordInfoFromGuids(__uuidof(structLib::__structLib), 1, 0, 0, __uuidof(structLib::MyStruct), &piRecInfo);
vtRec.pRecInfo = piRecInfo;
vtRec.pvRecord = &obj;      

PVOID pvItem = vtRec.pvRecord;    
CComVariant vtStr;
hr = piRecInfo->GetField(pvItem, L"m_sStr", &vtStr);
MessageBox(GetActiveWindow(), vtStr.bstrVal, vtStr.bstrVal, MB_OK);

Here, the C++ client runs and GetRecordInfoFromGuids() correctly returns

0x8002802b (Element not found)

when the struct definition is missing in the type library.

Is this behavior in vb6 by design? What's the cause? And is it possible to start the vb6 executable and catch error information, even when extracting type information of a referenced struct fails?

struct
com
vb6
midl
typelib
asked on Stack Overflow Feb 2, 2017 by Aurora • edited Feb 3, 2017 by Aurora

1 Answer

0

Is this behavior in vb6 by design?

I don't think so.

What's the cause?

When you assign a IDL structure to a VARIANT, the [uuid] attribute is intrinsically used. As it doesn't exist anymore, you get an exception.

That's what you do when calling GetRecordInfoFromGuids in C++, you provide explicitely the uuid of the IDL structure __uuidof(structLib::MyStruct).

And is it possible to start the executable even when extracting type information of a referenced struct fails?

I see 2 possibilities to achieve this goal:

  1. use late binding instead of early binding, and check the reference
  2. handle the exception which is thrown
answered on Stack Overflow Feb 2, 2017 by Jeandey Boris

User contributions licensed under CC BY-SA 3.0