Progid from Interface ID


Author: Dave
Date: 06.21.14 - 7:25am





Here is a hairy bit of code for you..

Lets say you have an IDispatch interface, you want to know what the publicly creatable CLSID and ProgID are for its class. How do you find it?

The TYPEATTR of the actual object you have ahold of, is an interface id. So you have to get the parent type library, enumerate its coclasses, enumate each coclasses implemented interfaces scanning for the IID you already have. Once found, then you use parent CoClass info to turn its TYPEATTR structures guid attribute into the ProgID and CLSID.

Much thanks to Igor Tandetnik news group post back from 5/30/07 on enumerating the steps to pull this off.

Below is some code for the brave of heart..

HRESULT FindCoClass(ITypeInfo* pti, GUID target, std::string &progid, std::string &clsid, std::string &version)
{
   HRESULT hr = S_OK;
   UINT count = 0;
   char buf[100];
   std::string tmp;
   WCHAR* pwszProgID = NULL;

   USES_CONVERSION;
   UINT index=0;
   
   CComPtr<ITypeLib> spTypeLib = NULL;
    hr = pti->GetContainingTypeLib(&spTypeLib, &index);

   if(SUCCEEDED(hr) && spTypeLib){
      
      UINT cnt = spTypeLib->GetTypeInfoCount();
      for(int i=0; i < cnt; i++){
         TYPEKIND tk;
         CComPtr<ITypeInfo> spTypeInfo = NULL;
         hr = spTypeLib->GetTypeInfoType(i, &tk);
         if(SUCCEEDED(hr)){
            if(tk == TKIND_COCLASS){
               hr = spTypeLib->GetTypeInfo(i, &spTypeInfo);
               if(SUCCEEDED(hr) && spTypeLib){
                  TYPEATTR *ta = NULL;
                  hr = spTypeInfo->GetTypeAttr(&ta);
                  if(SUCCEEDED(hr) && ta){
                     for(int j=0; j< ta->cImplTypes; j++){
                        HREFTYPE ht;
                        TYPEATTR *ta2 = NULL;
                        CComPtr<ITypeInfo> ti2 = NULL;

                        spTypeInfo->GetRefTypeOfImplType(j,&ht);
                        hr = spTypeInfo->GetRefTypeInfo(ht, &ti2);
                        if(SUCCEEDED(hr) && ti2){
                           hr = ti2->GetTypeAttr(&ta2);
                           if(SUCCEEDED(hr) && ta2){
                              if(ta2->guid == target){ //we found our match..
                                 sprintf(buf, "%d.%d", ta->wMajorVerNum, ta->wMinorVerNum);
                                 version = buf;
                                 if (!FAILED(hr = (ProgIDFromCLSID(ta->guid,&pwszProgID))))
                                 {
                                    progid = W2A(pwszProgID);
                                    CoTaskMemFree(pwszProgID);
                                 }
                                 if (!FAILED(hr = (StringFromCLSID(ta->guid,&pwszProgID))))
                                 {
                                    clsid = W2A(pwszProgID);
                                    CoTaskMemFree(pwszProgID);
                                 } 
                                 ti2->ReleaseTypeAttr(ta2);
                                 spTypeInfo->ReleaseTypeAttr(ta);
                                 return S_OK;
                              }
                              ti2->ReleaseTypeAttr(ta2);
                           }
                        }
                     }
                     spTypeInfo->ReleaseTypeAttr(ta);
                  }
               }   
            }
         }
      }
   }
     return 0;
}


And example usage:

HRESULT GetIDispatchMethods(IDispatch* pDisp, std::list &methods)
{
    HRESULT hr = S_OK;
    UINT count = 0;
    char buf[100];
    std::string tmp;
    std::string progid;
    std::string clsid;
    std::string version;

    USES_CONVERSION;

    CComPtr<IDispatch> spDisp(pDisp);
    if(!spDisp)
        return E_INVALIDARG;

    CComPtr<ITypeInfo> spTypeInfo = NULL;
    hr = spDisp->GetTypeInfo(0, 0, &spTypeInfo);

    if(SUCCEEDED(hr) && spTypeInfo)
    {
        TYPEATTR *pTatt = nullptr;
        hr = spTypeInfo->GetTypeAttr(&pTatt);
		
        if(SUCCEEDED(hr) && pTatt)
        {
           hr = FindCoClass(spTypeInfo,pTatt->guid, progid, clsid, version);
           if(progid.length() > 0)methods.push_back("ProgID: " + progid); 
           if(clsid.length() > 0)methods.push_back("CLSID: " + clsid);
           if(version != "0.0") methods.push_back("Version: " + version);

....





Comments: (1)

On 06.21.14 - 7:30am Dave wrote:
You can find a working example in the safe_array.zip demo

I should also mention the context of this is for dealing with public ActiveX control interfaces that support ITypeInfo. VB6 Form objects for example, while they are COM objects and do support IDispatch and are scriptable, do not support a full ITypeInfo because the interface is not public and they do not have type library entries. Basically it seems like they support just enough so that the VB6 TypeName() function always works.

Actually sometimes VB6 form objects do have a full implementation of ITypeInfo functions, but only while running in the IDE. I believe this is related to the internal workings of the IDE intellisense.

 
Leave Comment:
Name:
Email: (not shown)
Message: (Required)
Math Question: 69 + 40 = ? followed by the letter: S 



About Me
More Blogs
Main Site
Posts: (All)
2020 ( 2 )
2019 ( 5 )
2018 ( 6 )
2017 ( 6 )
2016 ( 22 )
2015 ( 16 )
2014 (25)
     Query Last 12 Mos
     Progid from Interface ID
     VB6 to C Array Examples
     Human Readable Variant Type
     ScriptBasic COM Integration
     CodeView Addin
     ScriptBasic - Part 2
     Script Env
     MSCOMCTL Win7 Error
     printf override
     History Combo
     Disable IE
     API Hooking in VB6
     Addin Hook Events
     FastBuild Addin
     VB6 MemoryWindow
     Link C Obj Files into VB6
     Vb6 Standard Dlls
     CStr for Pascal
     Lazarus Review
     asprintf for VS
     VB6 GlobalMultiUse
     Scintilla in VB6
     Dynamic Highlight
     WinVerifyTrust, CryptMsgGetParam VB6
2013 ( 4 )
2012 ( 10 )
2011 ( 7 )
2010 ( 11 )
2009 ( 3 )