Search code examples
comregistrycreateobjectclsid

Discovering registered COM components


Is there a way to determine if a registered COM component is creatable as a stand-alone component simply by parsing the information available in the registry? In particular, by the information found in HKCR/ClsId?

My system has over 12,000 entries in this key, and I am already excluding any items that do not have an InProcServer32 or LocalServer32 key, but this only eliminates about half of the items. I believe there are still another couple thousand that are not creatable objects. I really don't want to have to attempt to do a CreateObject() on every one of them to distinguish the ones that can be created from the ones that cannot. Is there a more efficient way?


Solution

  • Oleview

    I used Oleview for this purpose (back in the day :))

    Manual/programmatic

    If I remember correctly (no Windows PC nearby):

    • the class should link to a typelibrary
    • the typelib will point to a binary (dll, ocx, exe)
    • this binary contains the physical typelibrary, which you should parse
      • the midl compiler can do that (generate stubs/C headers)
      • oleview can do that (extract IDL)
      • tlbimp can do that
      • you can do it with Win32 API
      • any creatable objects should be marked coclass (not interface or source; there were also global modules which I suppose are creatable too: I'm just not sure whether they are defined as coclasses

    Show me the code

    It is possible to read the information within a type library with the ITypeLib and ITypeInfo interfaces. They can be created with the ICreateTypeLib and ICreateTypeInfo interfaces. However, the Microsoft IDL compiler (MIDL) is probably the only application to ever use ICreateType and ICreateTypeInfo.

    A quick google turned up this useful page: Reading Type Libraries with C++.

    It contains just the code to get started. Just to see whether it was worth anything, I fired up a cloud Windows instance, grabbed all the sources and compiled it.

    In contrast with the options mentioned on the site, I simply compiled on windows with

    cl.exe *.cpp /EHs ole32.lib oleaut32.lib
    

    Just for fun, I compiled the stuff on Linux (64 bit) using MingW:

    i586-mingw32msvc-g++ *.cpp -loleaut32 -lole32 -o Typelib.exe
    

    To save you the work I have put a zip-file up for download containing:

    win32_Unicode.cpp     - sources by René Nyffenegger
    win32_Unicode.h
    TestTypelib.cpp
    Typelib.cpp
    Typelib.h
    VariantHelper.cpp
    VariantHelper.h
    TestTypelib.exe       - binary compiled on windows
    

    A test run:

    # linux: ./a.exe ~/.wine/drive_c/windows/system32/msxml6.dll
    C:\Games\Stacko>TestTypelib.exe c:\Windows\System32\msxml6.dll
    
    MSXML2: Microsoft XML, v6.0
    Nof Type Infos: 149
    
    IXMLDOMImplementation
    ----------------------------
      Interface: Dispatch
      functions: 8
      variables: 0
    
      Function     : QueryInterface
        returns    : VT_VOID
        flags      : 
        invoke kind: function
        params     : 2
        params opt : 0
        Parameter  : riid type = VT_PTR (VT_USERDEFINED (GUID)) in
        Parameter  : ppvObj type = VT_PTR (VT_PTR) out
    
      Function     : AddRef
        returns    : VT_UI4
        flags      : 
        invoke kind: function
        params     : 0
        params opt : 0
    

    (snip) and 15499 lines more

    Concluding

    I hope this gives you a good starting point in scanning your system for installed, creatable, COM components