• Welcome to Powerbasic Museum 2020-B.
 

News:

Forum in repository mode. No new members allowed.

Main Menu

How To Find Source Interfaces In TypeLib?

Started by Frederick J. Harris, December 18, 2011, 06:51:11 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Frederick J. Harris

How does one determine that an interface is attributed with the 'source' IDL attribute, that is, that it is an event interface?  Of course, one could do a text comparison search on all the interface names in a Type Library looking for the 'Events' string in an interface name, such as 'Events' found in DMSFlexGridEvents, which is interface index # 27 in the MSFlexGridLib, but that somehow doesn't seem like a high quality solution.  I'm aware that the Type Library interfaces contain methods to accomplish this, but they simply don't work, or there is no adequate documentation to describe how they can be made to work. 

For example, the ITypeInfo interface contains the GetImplTypeFlags method which should return an enum as below...


HRESULT ITypeInfo::GetImplTypeFlags
(
  unsigned int  index, 
  int*          pImplTypeFlags 
);

Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface or base interface in a type description.

Parameters

index           Index of the implemented interface or base interface for which to get the flags.
pImplTypeFlags  On return, pointer to the IMPLTYPEFLAGS enumeration.


And the IMPLTYPEFLAGS enumeration is as follows...


IMPLTYPEFLAGS

Defined as follows:

#define IMPLTYPEFLAG_FDEFAULT        0x1
#define IMPLTYPEFLAG_FSOURCE         0x2
#define IMPLTYPEFLAG_FRESTRICTED     0x4
#define IMPLTYPEFLAG_FDEFAULTVTABLE  0x800

Value Description

IMPLTYPEFLAG_FDEFAULT                The interface or dispinterface represents the default for the source or sink.
IMPLTYPEFLAG_FSOURCE                 This member of a coclass is called rather than implemented.
IMPLTYPEFLAG_FRESTRICTED             The member should not be displayed or programmable by users. 
IMPLTYPEFLAG_FDEFAULTVTABLE          Sinks receive events through the VTBL.


The IMPLTYPEFLAG_FSOURCE is exactly what I am looking for, but there is no documented way to retrieve it.  Well, perhaps I should rephrase that.  There is no documented way to retrieve it that works.  So I guess what I am asking for is the undocumented way to retrieve it that works, because I'm quite aware that both Jose's and the PowerBASIC COM Browsers retrieve this info.

If one were to simply go by Microsoft's documentation to retrieve this info (which is how I routinely do things) one could write a program such as this....


#define  UNICODE
#define  _UNICODE
#include <windows.h>
#include <tchar.h>
#include <cstdio>
const    IID LIBID_Component = {0x5E9E78A0,0x531B,0x11CF,{0x91,0xF6,0xC2,0x86,0x3C,0x38,0x5E,0x30}}; //MSFlexGridLib 1, 0

int main(void)
{
BSTR strLibName,strInterfaceName;
ITypeInfo* pTypeInfo=NULL;
TYPEATTR* pTypeAttr=NULL;
ITypeLib* pTypeLib=NULL;
HREFTYPE  pRefType=NULL;
int pImplTypeFlags=0;
int iTypeInfoCount=0;
TYPEKIND pKind;
HRESULT hr;

CoInitialize(NULL);                           
hr=LoadRegTypeLib(LIBID_Component,1,0,0,&pTypeLib);                     //Load MSFlexGridLib
if(SUCCEEDED(hr))
{
    hr=pTypeLib->GetDocumentation(-1,&strLibName,NULL,NULL,NULL);        //Get Name Of Lib
    wprintf(L"strLibName        = %s\n",strLibName);
    SysFreeString(strLibName);
    hr=pTypeLib->GetTypeInfoType(27,&pKind);                             //Get pKind for index 27, i.e., DMSFlexGridEvents
    printf("pKind             = %u\n",pKind);
    if(pKind==4)
       printf("pKind             = TKIND_DISPATCH\n");
    hr=pTypeLib->GetDocumentation(27,&strInterfaceName,NULL,NULL,NULL);  //Get Name of index 27, i.e., DMSFlexGridEvents
    wprintf(L"strInterfaceName  = %s\n",strInterfaceName);
    SysFreeString(strInterfaceName);
    hr=pTypeLib->GetTypeInfo(27,&pTypeInfo);                             //Get ITypeInfo* for index 27, i.e., DMSFlexGridEvents 
    if(SUCCEEDED(hr))                                 
    {
       hr=pTypeInfo->GetImplTypeFlags(0,&pImplTypeFlags);                //This method call will fail for every index except
       if(SUCCEEDED(hr))                                                 //zero.  The method call will succeed for an index of
       {                                                                 //zero in terms of S_OK, but will fail to retrieve any
          printf("The Method Call ITypeInfo::GetImplTypeFlags() Succeeded, But It Really Failed!!!!\n");  //number other than zero.
          printf("\npImplTypeFlags    = %d\n",pImplTypeFlags);
       }                                                                 
       pTypeInfo->Release();                                 
    }   
    pTypeLib->Release();
}
CoUninitialize();
getchar();

return 0;
}

/*
strLibName        = MSFlexGridLib
pKind             = 4
pKind             = TKIND_DISPATCH
strInterfaceName  = DMSFlexGridEvents
The Method Call ITypeInfo::GetImplTypeFlags() Succeeded, But It Really Failed!!!!

pImplTypeFlags    = 0
*/


Even though my call to ITypeInfo::GetImplTypeFlags() returned a success code, it failed to retrieve the information as can be seen above in pImplTypeFlags = 0.  But even if that did work it presupposes knowledge of which interface is the events interface, which is index 27 in the MSFlexGridLib.  It should be possible to interrogate the CoClasses for this information.  For example, index 28 in the MSFlexGridLib is CoClass MSFlexGrid as follows...


coclass MSFlexGrid
{
[default]           interface IMSFlexGrid;
[default, source]   dispinterface DMSFlexGridEvents;
};


The second interface there, i.e., [default, source]   dispinterface DMSFlexGridEvents, is marked with the source attribute.  It should be possible to obtain that information first, then use it to do whatever one wants to do with it.  But that doesn't work either.  I am able to index into the CoClass and obtain the BSTR name 'DMSFlexGridEvents', but when I get a ITypeInfo* for it I end up with the same success that is really a failure as shown above.  Here is that program and its output...


#define  UNICODE
#define  _UNICODE
#include <windows.h>
#include <tchar.h>
#include <cstdio>
#define  MAX_NAMES  48
const    IID LIBID_Component = {0x5E9E78A0,0x531B,0x11CF,{0x91,0xF6,0xC2,0x86,0x3C,0x38,0x5E,0x30}};   // MSFlexGridLib 1, 0

int main(void)
{
ITypeInfo* pTypeInfo=NULL;
TYPEATTR* pTypeAttr=NULL;
ITypeLib* pTypeLib=NULL;
HREFTYPE  pRefType=NULL;
int iTypeInfoCount=0;
TYPEKIND pKind;
BSTR strName;
HRESULT hr;

CoInitialize(NULL);                           
hr=LoadRegTypeLib(LIBID_Component,1,0,0,&pTypeLib);
if(SUCCEEDED(hr))
{
    hr=pTypeLib->GetDocumentation(-1,&strName,NULL,NULL,NULL);
    wprintf(L"%s\n",strName);
    SysFreeString(strName);
    hr=pTypeLib->GetTypeInfoType(28,&pKind);
    printf("pKind = %u\n",pKind);
    if(pKind==TKIND_COCLASS)
       printf("Index #28 Is A CoClass\n");
    hr=pTypeLib->GetDocumentation(28,&strName,NULL,NULL,NULL);
    wprintf(L"strName = %s\n",strName);
    SysFreeString(strName);
    hr=pTypeLib->GetTypeInfo(28,&pTypeInfo);   // Get TYPEINFO* For CoClass MSFlexGrid; index 28
    if(SUCCEEDED(hr))                          // Then get TYPEATTR*; TYPEATTR::cImplTypes;       
    {                                          // Number of implemented interfaces.
       hr=pTypeInfo->GetTypeAttr(&pTypeAttr);  // There are two ( 0 ) IMSFlexGrid and ( 1 ) DMSFlexGridEvents
       printf("pTypeAttr->cImplTypes = %u\n",pTypeAttr->cImplTypes); //  << that <<< returns 2.
       hr=pTypeInfo->GetRefTypeOfImplType(1,&pRefType);
       if(SUCCEEDED(hr))
       {
          ITypeInfo* pRefTypeInfo=NULL;
          hr=pTypeInfo->GetRefTypeInfo(pRefType,&pRefTypeInfo);
          if(SUCCEEDED(hr))
          {
             hr=pRefTypeInfo->GetDocumentation(-1,&strName,NULL,NULL,NULL);
             wprintf(L"%s\n",strName);
             SysFreeString(strName);
             int pImplTypeFlags=0;
             hr=pRefTypeInfo->GetImplTypeFlags(0,&pImplTypeFlags);
             if(SUCCEEDED(hr))
             {
                printf("pRefTypeInfo->GetImplTypeFlags(1,&pImplTypeFlags) Succeeded!\n");
                printf("pImplTypeFlags = %d\n",pImplTypeFlags);
             }
             pRefTypeInfo->Release();
          }
       }
       pTypeInfo->ReleaseTypeAttr(pTypeAttr);
       pTypeInfo->Release();
    }
    pTypeLib->Release();
}
CoUninitialize();
getchar();

return 0;
}

/*
MSFlexGridLib
pKind = 5
Its A CoClass
strName = MSFlexGrid
pTypeAttr->cImplTypes = 2
DMSFlexGridEvents
pRefTypeInfo->GetImplTypeFlags(1,&pImplTypeFlags) Succeeded!
pImplTypeFlags = 0
*/


So I'll end this with the question I asked in my first sentence.  How does one determine that an interface is an event (source) interface without performing the dubious activity of searching text strings of interface names for 'Events'?



José Roca

Quote
       hr=pTypeInfo->GetTypeAttr(&pTypeAttr);  // There are two ( 0 ) IMSFlexGrid and ( 1 ) DMSFlexGridEvents
       printf("pTypeAttr->cImplTypes = %u\n",pTypeAttr->cImplTypes); //  << that <<< returns 2.

This is what I use:


' ---------------------------------------------------------------------
' Gets the default events interfaces for each CoClass
' ---------------------------------------------------------------------
cImplTypes = @pTypeAttr.cImplTypes
FOR x = 0 TO cImplTypes - 1
   lImplTypeFlags = 0
   hr = pITypeInfo.GetImplTypeFlags(x, lImplTypeFlags)
   IF hr <> %S_OK THEN EXIT FOR
   pRefType = 0
   hr = pITypeInfo.GetRefTypeOfImplType(x, pRefType)
   IF hr <> %S_OK THEN EXIT FOR
   hr = pITypeInfo.GetRefTypeInfo(pRefType, pImplTypeInfo)
   IF hr <> %S_OK OR ISFALSE ISOBJECT(pImplTypeInfo) THEN EXIT FOR
   hr = pImplTypeInfo.GetDocumentation(-1, bstrName, BYVAL %NULL, BYVAL %NULL, BYVAL %NULL)
   IF hr <> %S_OK THEN EXIT FOR
   pImplTypeInfo = NOTHING
   szInterfaceName = bstrName
   IF lImplTypeFlags = 1 THEN        ' // Default interface
      ' --- Do something
   ELSEIF lImplTypeFlags = 2 OR lImplTypeFlags = 3 THEN    ' // Events interface / Default events interface
      ' --- Do something
   END IF
NEXT


Frederick J. Harris

Thanks Jose (yet again).  I'll give it a try first thing tomorrow.  I was wondering if it might be something like that similiar to getting the base interface of an interface.