Writing a simple Typelibrary browser

Type libraries provide a wealth of benefits:

They allow OLE/Automation clients to get to know the server’s properties and methods
during compile time.
Most IDE’s allow you to import typelibraries and then generate wrappers for you based
on the information contained in the Type Library.
For example: Class Wizard’s Import Type Library option that generates a COleDispatchDriver wrapper.
Smart pointer generation definitions like #import also use the typelibrary to generate smart pointer based wrappers.
All this magic works because of Typelibraries

Type libraries allow clients to statically bind (also known as early binding) to a COM interface’s
supported methods and properties.

Given below are some of the advantages of early binding:
Checking for correct data types can be performed at compile time itself allowing the
client application developer to pass the right data types.
Any errors in passing non coercible data types are checked at compile time itself
Clients that cannot bind to Vtables can use this form of binding to get to the server.

Type Library marshalling is also useful if OLE Automation compatible data types are used, allowing
you to do away with the creation of a proxy/stub dll for Local Server(out of proc server) access.

Visual Basic clients can use the Type Library to bind to an interface they require rather that get
to the generic Object Type.

Also once you get access to the dispatch IDs from the typelibrary (DISPIDs) , you can use Invoke()
method of IDispatch to invoke an object’s method and properties.

Follow on to see how we pick up all the registered type libraries in your machine.

Writing the Typelibrary browser:

Step 1:
Enumerating thru the Registry keys and picking up all registered type libraries

You’ll find all the registered type libraries under HKEY_CLASSES_ROOT\TypeLib.
Under this section, every subkey is the CLSID of the TypeLibrary.
Enumerate through this section and pick up all the CLASSIDs of the registered typelibraries.
Once you get the HKCR\TypeLib\{XXX….XXX} , you need to hunt for the version information and the
default value of the version information string conatins a named description of the typelibrary.

These version keys generally take the format MajorVersion.MinorVersion (eg: 1.0)
You’ll find the TypeLibrary enumeration in the function EnumerateRegistryForTypeLibEntries().
This function contains nested enumeration loops , an outer loop that picks up the CLSIDs under the TypeLib key
and an inner enumeration loop that picks up multiple versions of the TypeLibrary.

Step 2:
Loading the TypeLibrary and picking up the Type Information:

Now that we have got all our registered Type Library names and their associated CLSIDs, let’s open up a
typelibrary and see what interfaces/dispinterfaces , classes , enumerations etc. that it contains.
Getting to this information requires you to get a ITypeLib interface
So given a class ID of the Type library, it’s major version and minor version, you can pick up a
pointer to the ITypeLib interface.
Here’s how you get it:

hr = LoadRegTypeLib (clsidTypeLib,
(unsigned short)pData->m_lMajorVersion,
(unsigned short)pData->m_lMinorVersion,
0,
&m_pTypeLib) ;

Getting the help file name and other documentation related information is done through the GetDocumentation()
method of ITypeLib. Pay careful attention to the index that is passed to the first parameter (-1).
Passing -1 gets back all the details for the Type library and passing an index (0 to nTypeInfoCount -1) allows you to get the
documentation details of the Type Info components(typically dispinterfaces, typedefs, interfaces,enumerations etc.) within the Typelibrary.

m_pTypeLib->GetDocumentation((unsigned int)-1,
NULL,
&bstrHelpString,
NULL,
&bstrHelpFileName);

Now it’s time to pick up the Type Information. First pick up the count of the number of Type Information
components available.
Then iterate through a loop and pick up the type information details.

//Get the type information count
lTypeInfoCount = m_pTypeLib->GetTypeInfoCount();

//Make sure that we have type information
if(lTypeInfoCount == 0)
{
bSuccess = FALSE;
}

if(bSuccess)
{

//Get the help string and help file for each TypeInfo
for(long lIter = 0; lIter < lTypeInfoCount ; lIter++)
{

m_pTypeLib->GetDocumentation(lIter, &bstrName, NULL, NULL, NULL);
this->m_ListTypeInfo.InsertItem(lIter,CString(bstrName),3);
if(bstrName) ::SysFreeString(bstrName);

}

}

Step 3:
Getting the kind for each Type Info Component:

Using the GetTypeInfoType() method of ITypeLib, you can populate a TYPEKIND structure that can be used
to index into an array of descriptions for the kind of Type information.
You can now find out whether each type information component is an interface, a dispatch interface,
a typedef, an enumeration etc.

static char* g_arrClassification[] = { “Enum”,“Struct”,“Module”,“Interface”,
“Dispinterface”,“Coclass”,“Typedef”,“Union”};

//Get the information about the TypeInfo
hr = m_pTypeLib->GetTypeInfoType((unsigned int)dwIndex, &typeKind);

//index into our global array to pick up the description
if(hr != S_OK)
{
bSuccess = FALSE;
m_strTypeDescription = “”;
}
else
{

m_strTypeDescription = g_arrClassification[typeKind];

}

Step 4:
Getting the attributes of a TypeInfo component:

To get the methods , properties or enumerated values provided by a type info component,
you first need to get a ITypeInfo interface. From the ITypeInfo interface, get the type
attributes (a TYPEATTR structure) that holds the number of attributes contained in each
type information component.
Here’s how you get the methods and properties that are supported by an interface.
Get the number of methods and properties in the specific Type Info component by using the
cFuncs (for Methods) and cVars (for properties and enumerations) member of the TYPEATTR structure.
The loop through and populate the FUNCDESC and VARDESC structure using the GetFuncDesc() and GetVarDesc() method of ITypeInfo

//Get the TypeAttributes
m_pCurrentTypeInfo->GetTypeAttr(&pTypeAttributes);

int iIndex = 0;
//Lets get all the methods for this Type Info
for(int iIter = 0; iIter < pTypeAttributes->cFuncs; iIter++)
{

//Get the function description
m_pCurrentTypeInfo->GetFuncDesc(iIter, &pFuncDesc) ;

//Get the member ID
memberID = pFuncDesc->memid;

//Get the name of the method
m_pCurrentTypeInfo->GetDocumentation(memberID, &bstrMethod, NULL, NULL, NULL);

this->m_ListTypeAttribs.InsertItem(iIndex,CString(bstrMethod),1);

if(bstrMethod) ::SysFreeString(bstrMethod);

//Release our function description stuff
m_pCurrentTypeInfo->ReleaseFuncDesc(pFuncDesc);

iIndex++;

}

//Here’s how you pick up all the properties and enumerated types supported

for(iIter = 0; iIter < pTypeAttributes->cVars; iIter++)
{

//Get the property description
m_pCurrentTypeInfo->GetVarDesc(iIter, &pVarDesc) ;

//Get the member ID
memberID = pVarDesc->memid;

//Get the name of the property
m_pCurrentTypeInfo->GetDocumentation(memberID, &bstrProperty, NULL, NULL, NULL);

this->m_ListTypeAttribs.InsertItem(iIndex,CString(bstrProperty),0);

if(bstrProperty) ::SysFreeString(bstrProperty);

//Release our variable description stuff
m_pCurrentTypeInfo->ReleaseVarDesc(pVarDesc);

iIndex++;

}

You now have a type library browser that let’s you browse through all the registered type libraries in your system.

Download source- 45 KB

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read