To parse the type library information we need to call the methods of the ITypeInfo interface.
This is my definition of that interface:
' ########################################################################################
' Interface name = ITypeInfo
' Extracts information about the characteristics and capabilities of objects from type libraries.
' Inherited interface = IUnknown
' ########################################################################################
TYPE Afx_ITypeInfo AS Afx_ITypeInfo_
#ifndef __Afx_ITypeInfo_INTERFACE_DEFINED__
#define __Afx_ITypeInfo_INTERFACE_DEFINED__
TYPE Afx_ITypeInfo_ EXTENDS Afx_IUnknown
DECLARE ABSTRACT FUNCTION GetTypeAttr (BYVAL ppTypeAttr AS TYPEATTR PTR PTR) AS HRESULT
DECLARE ABSTRACT FUNCTION GetTypeComp (BYVAL ppTComp AS ITypeComp PTR PTR) AS HRESULT
DECLARE ABSTRACT FUNCTION GetFuncDesc (BYVAL index AS UINT, BYVAL ppFuncDesc AS FUNCDESC PTR PTR) AS HRESULT
DECLARE ABSTRACT FUNCTION GetVarDesc (BYVAL index AS UINT, BYVAL ppVarDesc AS VARDESC PTR PTR) AS HRESULT
DECLARE ABSTRACT FUNCTION GetNames (BYVAL memid AS MEMBERID, BYVAL rgBstrNames AS AFX_BSTR PTR, BYVAL cMaxNames AS UINT, BYVAL pcNames AS UINT PTR) AS HRESULT
DECLARE ABSTRACT FUNCTION GetRefTypeOfImplType (BYVAL index AS UINT, BYVAL pRefType AS HREFTYPE PTR) AS HRESULT
DECLARE ABSTRACT FUNCTION GetImplTypeFlags (BYVAL index AS UINT, BYVAL pImplTypeFlags AS INT_ PTR) AS HRESULT
DECLARE ABSTRACT FUNCTION GetIDsOfNames (BYVAL rgszNames AS LPOLESTR PTR, BYVAL cNames AS UINT, BYVAL pMemId AS MEMBERID PTR) AS HRESULT
DECLARE ABSTRACT FUNCTION Invoke (BYVAL pvInstance AS PVOID, BYVAL memid AS MEMBERID, BYVAL wFlags AS WORD, BYVAL pDispParams AS DISPPARAMS PTR, BYVAL pVarResult AS VARIANT PTR, BYVAL pExcepInfo AS EXCEPINFO PTR, BYVAL puArgErr AS UINT PTR) AS HRESULT
DECLARE ABSTRACT FUNCTION GetDocumentation (BYVAL memid AS MEMBERID, BYVAL pBstrName AS AFX_BSTR PTR, BYVAL pBstrDocString AS AFX_BSTR PTR, BYVAL pdwHelpContext AS DWORD PTR, BYVAL pBstrHelpFile AS AFX_BSTR PTR) AS HRESULT
DECLARE ABSTRACT FUNCTION GetDllEntry (BYVAL memid AS MEMBERID, BYVAL invKind AS INVOKEKIND, BYVAL pBstrDllName AS AFX_BSTR PTR, BYVAL pBstrName AS AFX_BSTR PTR, BYVAL pwOrdinal AS WORD PTR) AS HRESULT
DECLARE ABSTRACT FUNCTION GetRefTypeInfo (BYVAL hRefType AS HREFTYPE, BYVAL ppTInfo AS Afx_ITypeInfo PTR PTR) AS HRESULT
DECLARE ABSTRACT FUNCTION AddressOfMember (BYVAL memid AS MEMBERID, BYVAL invKind AS INVOKEKIND, BYVAL ppv AS PVOID PTR) AS HRESULT
DECLARE ABSTRACT FUNCTION CreateInstance (BYVAL pUnkOuter AS IUnknown PTR, BYVAL riid AS CONST IID CONST PTR, BYVAL ppvObj AS PVOID PTR) AS HRESULT
DECLARE ABSTRACT FUNCTION GetMops (BYVAL memid AS MEMBERID, BYVAL pBstrMops AS AFX_BSTR PTR) AS HRESULT
DECLARE ABSTRACT FUNCTION GetContainingTypeLib (BYVAL ppTLib AS Afx_ITypeLib PTR PTR, BYVAL pIndex AS UINT PTR) AS HRESULT
DECLARE ABSTRACT SUB ReleaseTypeAttr (BYVAL pTypeAttr AS TYPEATTR PTR)
DECLARE ABSTRACT SUB ReleaseFuncDesc (BYVAL pFuncDesc AS FUNCDESC PTR)
DECLARE ABSTRACT SUB ReleaseVarDesc (BYVAL pVarDesc AS VARDESC PTR)
END TYPE
#endif
To extract the type library information first wee need to rerieve how many TypeInfos it contains:
' // Retrieves the number of TypeInfos
TypeInfoCount = m_pTypeLib->GetTypeInfoCount
IF TypeInfoCount = 0 THEN
TLB_MsgBox m_pWindow->hWindow, "This TypeLib doesn't have type infos", _
MB_OK OR MB_ICONERROR OR MB_APPLMODAL, "CParseTypeLib.ParseTypeInfos"
RETURN S_FALSE
END IF
For each type info we will retrieve the type of a type description, a pointer to its ITypeInfo interface and a pointer to the TYPEATTR structure that contains the attributes of the type description.
FOR i = 0 TO TypeInfoCount - 1
' // Retrieves the TypeKind
hr = m_pTypeLib->GetTypeInfoType(i, @pTKind)
IF hr <> S_OK THEN
TLB_MsgBox m_pWindow->hWindow, "Error &H" & HEX$(hr, 8) & " retrieving the info type", _
MB_OK OR MB_ICONERROR OR MB_APPLMODAL, "CParseTypeLib.ParseTypeInfos"
EXIT FOR
END IF
' // Retrieves the ITypeInfo interface
hr = m_pTypeLib->GetTypeInfo(i, @pTypeInfo)
IF hr <> S_OK OR pTypeInfo = NULL THEN
TLB_MsgBox m_pWindow->hWindow, "Error &H" & HEX$(hr, 8) & " retrieving the ITypeInfo interface", _
MB_OK OR MB_ICONERROR OR MB_APPLMODAL, "CParseTypeLib.ParseTypeInfos"
EXIT FOR
END IF
' // Gets the address of a pointer to the TYPEATTR structure
hr = pTypeInfo->GetTypeAttr(@pTypeAttr)
IF hr <> S_OK OR pTypeAttr = NULL THEN
TLB_MsgBox m_pWindow->hWindow, "Error &H" & HEX$(hr, 8) & " retrieving the address of the TypeAttr structure", _
MB_OK OR MB_ICONERROR OR MB_APPLMODAL, "CParseTypeLib.ParseTypeInfos"
EXIT FOR
END IF
...
...
...
NEXT
Inside the loop, we will process each block of information separately according its type:
SELECT CASE pTKind
CASE TKIND_COCLASS ' // CoClasses
...
...
...
CASE TKIND_RECORD, TKIND_UNION ' // Structures and unions
...
...
...
CASE TKIND_ALIAS ' // Aliases and typedefs
...
...
...
CASE TKIND_ENUM, TKIND_MODULE ' // Enumerations and modules
...
...
...
CASE TKIND_INTERFACE, TKIND_DISPATCH ' // Interfaces
...
...
...
END SELECT