Writing a simple Typelibrary browser


Desktop-as-a-Service Designed for Any Cloud ? Nutanix Frame

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,
		    &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, 


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;

		//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);
		  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",


	//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 = "";
		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

	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);


	  if(bstrMethod) ::SysFreeString(bstrMethod);

		//Release our function description stuff



	//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);
	  if(bstrProperty) ::SysFreeString(bstrProperty);

		//Release our variable description stuff



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

This article was originally published on December 1st, 1998

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date