My question is similar to Getting CLSID for a DLL file?, I think.
I have a directory with some DLLs, each one implementing one or more COM interfaces. I would like to ge
You might want to look at the source code in WiX's heat utility, which does the same thing:
http://wix.sourceforge.net/manual-wix3/heat.htm
Few caveats to Ben Voigt's answer: not every COM DLL has a typelib. In your case, it seems, it does; but that's not a requirement. The only rock-solid requirement is that the DLL exports the function DllGetClassObject(), where you pass a CLSID and get back an object factory.
You could load the library and call DllGetClassObject for every registered CLSID on the system (scan the registry under HKCR\CLSID for the list of those). The ones where you get a valid object back are the ones that the DLL supports. Now, in theory, it's not even a requirement that the CLSIDs the DLL supports are registered; I can envision a DLL that implements private object classes that only the intended client knows about and no one else should. But this is a very, very exotic scenario; for one thing, the regular COM mechanism of looking up the DLL path by the CLSID will break for those. The client would have to load the DLL directly.
You could also scan the registry for the CLSID's where the DLL under consideration is registered as InprocServer32; this, again, will break in case of private classes. You can do a registry search in regedit
, search in data. Also, you'd have to deal with filename case issues, short vs. long names, hardlinks, environment variable substitution and so on. So I would not recommend it.
EDIT: just thought of another way. Download Regmon, run it, and call regsvr32 on the DLL. Then watch what CLSID's are touched.
You can't get that from the COM DLL, but you can get it from the typelib. I'm pretty sure the MIDL compiler has a switch to decompile a typelib, but parsing IDL wouldn't be as easy as using the TypeLib API.
To complicate matters, the typelib is often stored as a resource inside the DLL. So you'd extract the resource, and open it with the TypeLib API.
Start with LoadTypeLibEx which will return you an ITypeLib*
interface pointer (you knew you were going to need COM in order to get information about COM libraries, right?). This will actually do the resource extraction step for you.
Then, call ITypeLib::GetTypeInfoCount to find out how many types there are. Call ITypeLib::GetTypeInfoType for each one to find the interfaces and coclasses. And call ITypeLib::GetTypeInfo followed by ITypeInfo::GetDocumentation to get the name.
It looks like you have all of this so far. Next you need the GUID of the type, which is gotten with ITypeInfo::GetTypeAttr (not ITypeLib::GetLibAttr
). That gives you a TYPEATTR structure, which has a guid
field.
From the same TYPEATTR
structure, you'll need the cImplTypes
field. That together with ITypeInfo::GetRefTypeOfImplType will let you match up each coclass to the interfaces it implements.
Note that there's not guaranteed to be a 1:1 relationship between interfaces and implementation coclasses. And the interface can be in a different library from the coclass.