How can I get TypeLibInfo from an ITypeLib pointer?

640 Views Asked by At

I would like to use the tlbinf32.dll to read type info for a COM object. At the moment I have access to the pointer to the ITypeLib interface. I can use VTable offsets and DispCallFunc to manually call methods and navgate, however I was hoping to use the powerful builtin capabilities of that library.

I was thinking that since TLI.ClassInfoFromObject(Object As IUnknown) can be used to query the IDispatch::GetTypeInfo method, I could manually construct a dummy object that implements just this method to allow the TypeInfo to be read into memory. Similar to manually defining IEnumVariant where most of the methods just return E_NOTIMPL = &H80004001. Does this sound feasible? Is there a simpler way to access the TypeInfo from a pointer using VBA?


Update

To be clear, my problem is I can't find a way to declare the ITypeInfo interface and allow me to work with it directly - VBA accesses IUnknownfrom stole2.tlb so I can use that fine, but the only place I can find ITypeInfo declared is in mscorlib.dll, but it doesn't have the COMVisible attribute so there's no way to access it in VBA, AFAIK, and VBA doesn't have an equivalent to [ComImport] to let you define it with a GUID yourself. So I want to use tlbinf32.dll to save me having to use raw pointers.

1

There are 1 best solutions below

4
On

Turns out tlbinf32.dll supports this out of the box but it's hidden. From the help file:

ITypeLib As IUnknown
TypeLibInfoFromITypeLib(ByVal ptlib As IUnknown) As TypeLibInfo

Inside every TypeLibInfo is a reference to an ITypeLib instance. In fact, the TypeLibInfo object can be viewed as a wrapper on the ITypeLib interface which is easier to program against than ITypeLib itself. To see if two TypeLibInfo objects actually refer to the same internal object, use VB's Is operator with the ITypeLib property of the two objects. The Is operator will usually return False for TypeLibInfo objects which actually correspond to the same underlying type, but not for the internal ITypeLib pointers. The ITypeLib property is settable, so you can put a TypeLibInfo object on top of an existing ITypeLib.

If you have an ITypeLib reference and want to use TLI objects, then you can call TLI.TypeLibInfoFromITypeLib to generate a fully functional TypeLibInfo object.

The ITypeLib property and TypeLibInfoFromITypeLib method are considered advanced features and are marked as hidden.

emphasis my own

... similar story for an ITypeInfo pointer

So how to use? Quite simple. First a way to get the IUnknown from a pointer. e.g:

Public Function ObjectFromObjPtr(ByVal Address As LongPtr) As IUnknown
    Dim result As IUnknown
    MemLongPtr(VarPtr(result)) = Address
    Set ObjectFromObjPtr = result
    MemLongPtr(VarPtr(result)) = 0
End Function

Private Property Let MemLongPtr(ByVal dest as LongPtr, ByVal value As LongPtr)
    CopyMemory ByVal dest, value, LenB(value)
End Property

Followed by the call

Dim ITypeLibPtr As LongPtr
ITypeLibPtr = ... 'get the raw pointer

Dim ITypeLibObj As IUnknown
Set ITypeLibObj = ObjectFromObjPtr(ITypeLibPtr)

Dim NiceTypeLib As tli.TypeLibInfo
Set NiceTypeLib = tli.TypeLibInfoFrom(ITypeLibITypeLibObj)

or words to that effect