TLI Overview

Overview of TypeLib Information Objects

Object Model Diagram

The TypeLib Information object library (TLI for short, implemented in TlbInf32.dll) is a set of COM objects designed to make type library browsing functionality easily accessible to both Visual Basic and C++ programmers. Due to the flexibility and inherent subtleties inherent in type libraries, examining a type library via the native ITypeLib and ITypeInfo interfaces is a non-trivial task—even for an experienced C++ programmer. The goals of TLI are:

  • Provide full access to all of the data available via the ITypeLib and ITypeInfo interfaces via a structured object model hierarchy which parallels the native type library structure.

  • Create flexible collections which eliminate the need to explicitly walk every type in a type library, or every member in a type to accumulate presentable data.

  • Provide search functionality and bi-directional browsing capabilities. Generally, object models are viewed by selecting a type and viewing its members. TLI lets you select a member and view which type(s) it belongs to.

  • Present type library data in both a VB and a C++ friendly fashion. For example, a VB friendly collection of members shows a single member even though both a Property Get and a Property Let function are provided, and hides all base class dependencies.

  • Allow inspection and manipulation of any running COM object or Variant which contains browsable type information.

Smart Collections

Although TLI lets you walk a type library in a low level fashion using the TypeInfos and Members collections, wading through this information to generate a useable set of data is very cumbersome. TLI provides two types of prefiltered collections to let you look at something other than the raw typelib data. The first set of prefiltered collections are subsets of the TypeInfos collection; CoClasses (a collection of all createable classes in the type library) is an example of this type of collection. In addition to TypeInfos subsets, the TLI SearchResults object is a general purpose collection that can hold several types of pre-filtered data. For example, the following questions can be answered with a single method call that returns a SearchResults collection. See the Returned By list in the SearchResults topic for a list of all methods which return SearchResults collections.

  • Which classes in a given type library support a Click event? (GetTypesWithMemberEx)

  • What are the names of visible members of this class and all of its base classes? (GetMembers)

  • Which properties and methods of a given type library contain the letters 'rec'? (GetMembersWithSubStringEx)

  • Which Enums in the TLI type library begin with the letters 'tli'? (GetTypesWithSubString)

Methods which return SearchResults collections generally take a StartResults object, allowing you to place query information from multiple libraries in a single collection.

SearchResults collections are useful generating groups of types and members, but full information about a type or member is not stored in a SearchResults collection. However, the SearchItem objects in the collection contain sufficient information to all you to quickly index back into the TypeInfos collection. You can also directly retrieve a MemberInfo object using the GetMemberInfo method.

Filling Windows Directly

All methods which return SearchResults (except the two Ex methods) also have a Direct counterpart to allow you to dump data directly to a ListBox or ComboBox. For example, GetTypesDirect will place types directly into a ListBox control as opposed to GetTypes, which returns a SearchResults collection. The *Direct methods allows you to easily generate basic object browsing functionality.

Enums in TLI

The TLI type library contains a number of enums. Generally, enums which start with Tli are unique to TLI (TliSearchTypes, TliCustomFilterAction, etc). Members of these enums start with tli and an abbreviated version of the enum name, so tliStClasses is in the TliSearchTypes enum. Enums without a Tli are duplicates of enums in the OLE Automation headers. The exceptions to this rule are TliVarType, which is named to avoid conflicts with VBA, and InvokeKinds, which has some extra entries specifically for TLI.

Early Binding in TLI

TLI can be used in an entirely early bound fashion and is optimized for this case. If you call methods or properties from a TLI object stored in a Variant or Object parameter, then you force the TLI type library to load. Use of early bound code (and For Each) will never result in the type library being loaded to complete a method call. Over 50% of the on disk size of TlbInf32.dll is resources, and 75% of the resources size is attributable to the type library. As you can see from these percentages, forcing the type library into memory will drastically increase the TLI footprint.


TLI Object Model Diagram

Overview of TypeLib Information Objects


CustomDataCollection Property, CustomData Object

Applies To

Custom data in a type library refers to a setting which isn't covered by the normal set of attributes. This data is stored as a GUID/Value pair, where the GUID gives the category of data, and the Value is a Variant containing data about the category. Libraries, TypeInfos, Members, and individual parameters can all have custom data associated with them. To retrieve the extra data associated with an item, use the CustomDataCollection property.

A CustomDataCollection collection (1-based) has a Count and Item (default) property. The Item property returns a CustomData object which has a GUID property (returned as a string in registry format), and a Variant Value property. For a ParameterInfo object, you can first check the HasCustomData property before call CustomDataCollection, but this information isn't available for other objects without actually retrieving the collection. CustomDataCollection.Count will be 0 if no data is available.

Note that the Members collection must be used to retrieve MemberInfo and ParameterInfo objects which support CustomDataCollection. Otherwise, the property will raise tliErrDataNotAvailable.


Members Property and Collection

Applies To Members

The collection of MemberInfo objects available from a TypeInfo. MemberInfo objects are retrieved from the collection using the Item property with a 1-based index.

The Members collection contains completely raw data on the functions and variables of a TypeInfo object. The items appear in the order they arrive from the TypeInfo, and are not sorted or filtered in any way. There are several sources of confusion as to the items which actually in the Members collection:

  • Items which are generally restricted or hidden appear in the collection. For example, if the TypeInfo has TypeKind TKIND_DISPATCH, then the Members collection includes functions like QueryInterface, GetIDsOfNames, and Invoke. These functions are marked as restricted (see AttributeMask) and are generally not shown.

  • The Members collection can have multiple items with the same Name and MemberId, but different InvokeKind values. Therefore, to show a list which has unique names only, filtering is required.

  • The items in the Members collection may not reflect all of the properties and methods of the parent TypeInfo object. For example, if a TypeInfo has TypeKind TKIND_INTERFACE, then the Members collection will not include the members of the IUnknown interface (QueryInterface, AddRef, and Release). In order to see these members, use the ImpliedInterfaces method on the InterfaceInfo to retrieve members for the interfaces which are bases for the current object. Most objects will derive from IDispatch which derives from IUnknown, which you don't generally want to show anyway. However, there may be other base objects in between the top level and IDispatch, so you have to check these if using the Members collection directly.

  • The Members collection may have a different number of items if the TypeInfo object was retrieved using the VTableInterface property.

Since the point of the TLI library is to hide the underlying complexities inherent in type libraries, there are mechanisms built into the Dll such that you never have to walk the Members collection yourself if you're producing normal, object browser style information. The GetFilteredMembers and the GetMembers methods are provided to do all filtering and sorting for you.


Parameters Property and Collection

Applies To Members

The Parameters collection is used to retrieve ParameterInfo objects which correspond to a MemberInfo object which represents a function or property procedure. Individual items are retrieved using the default Item property. As with all TLI collections, the Parameters collection is 1-based, so valid indices are 1 to Count. Looking up a Parameter based on its name is not supported in TLI because parameters in type libraries do not have to be named.

The OptionalCount and DefaultCount properties give information about the number of required parameters. The Count property will be affected by the VTableInterface settings.


SearchResults Collection

Members Returned By

A SearchResults collection is a generic placeholder collection for data returned by methods listed in the Returned By list. A SearchResults collection contains SearchItem objects. Once you have a SearchResults collection, there are several things you can do with it:

  • Append more data to it by sending it as the StartResults parameter of any of the methods in the Returned By list (except GetMembers and GetFilteredMembers). This allows you to retrieve data from multiple TypeLibInfo objects into a single collection. Be sure to set the LibNum property of each library. If you're trying to merge incompatible data sets, the SearchResults-returning methods will raise error tliErrIncompatibleData

  • Sort the collection, using either default or custom Sort order.

  • Locate items in the collection by Name and/or custom conditions.

  • Filter the collection, which allows you to remove items from the collection, as well as creating new SearchResults collections based on the current data.


TypeInfos and Subset Collections

TypeInfos Collection and Subset Collections

Members Applies To

A type library can be loosely defined as a set of library-level attributes and a set of TypeInfo objects. The TypeLibInfo object has a number of collections which break the TypeInfos into subsets. The first subset is the TypeInfos collection, which simply includes every TypeInfo. The remaining subsets are categorized based on TypeKind. TypeInfos with type TKIND_ALIAS are resolved and placed into the correct category. The category groupings are shown in the table, with additional comments below.

Collection

Resolved TypeKind
TypeInfos | All
CoClasses | TKIND_COCLASS
Constants | TKIND_ENUM, TKIND_MODULE
Declarations | TKIND_MODULE
Interfaces | TKIND_INTERFACE, TKIND_DISPATCH
IntrinsicAliases | TKIND_ALIAS
Records | TKIND_RECORD
Unions | TKIND_UNION

TypeInfos:
The TypeInfos collection contains all TypeInfos and is very fast to generate. If you know the Name or TypeInfoNumber, you should use the accessor properties on this collection instead of generating a subset collection.

CoClasses:
The set of all creatable objects. These objects can be created using the New or CreateObject keywords in VB.

Constants:
The set of TypeInfos which contain constant values. This set can contain both enums and modules. However, a ConstantInfo type TypeInfo object with a TypeKind of TKIND_MODULE obtained from this collection generates a Members collection with the FuncFilter automatically set to –1, which keeps non-constant values out of the SearchResults collection returned by the GetFilteredMembers method.

Declarations:
The set of TypeInfos which contain function declarations which go directly to a Dll instead of a COM interface. Note that a TKIND_MODULE TypeInfo can appear in both the Constants and Declarations collections, although this is rare. Similar to the FuncFilter property with the Constants collection, the VarFilter property is automatically set to –1 for a Members collection generated from a DeclarationInfo object.

Interfaces:
The set of TypeInfos which correspond to interface definitions, meaning that all of these types derive from IUnknown and have a vtable. TKIND_DISPATCH TypeInfos in this collection support only the IDispatch vtable, whereas TKIND_INTERFACE (and dual TKIND_DISPATCH interfaces, see VTableInterface) support a vtable beyond IDispatch. This collection contains all interfaces in the type library, including those that are default interfaces of coclasses, and event interfaces. Since these interfaces are generally shown as part of the coclass when browsing a type library instead of standalone interfaces, the full set of interfaces is generally useful only when doing low-level type library operations. To get filtered sets of classes, interfaces, and other types; use the GetTypes method.

IntrinsicAliases:
The set of TypeInfos which are aliases to intrinsic data types. Note that, since all other collections resolve TKIND_ALIAS types to find the underlying type, TKIND_ALIAS TypeInfo objects may appear in all collections. IntrinsicAliases only contains TKIND_ALIAS TypeInfos which don't resolve to another TypeKind.

Records:
The set of TypeInfos which correspond to TKIND_RECORD. Records are also known as structures or user-defined types.

Unions:
The set of TypeInfos with a TypeKind of TKIND_UNION. Note that this is the only TypeKind not supported by VB.


MemberInfo Object

See Also Members

The MemberInfo object represents an individual function or variable in a TypeInfo object. For example, if Excel is a library and Worksheet a TypeInfo, then Calculate is a member function representable by a MemberInfo object.

MemberInfo objects fall into two distinct categories: Functions and Variables (Funcs and Vars). You can explicitly distinguish between a Func and Var using the DescKind property. Vars are associated with constant data and properties in non-dual TKIND_DISPATCH TypeInfo objects. Not all properties are Vars, as the InvokeKind property can also be used to flag a Func as a property.

You can retrieve a MemberInfo object from a Members collection using an index, the GetMember property, or the GetMemberInfo method.

The most commonly used properties on the MemberInfo object are Name, MemberId, Parameters, and ReturnType.

Note that retrieving a MemberInfo object from the Members collection is required to avoid the error tliErrDataNotAvailable on some MemberInfo properties. Retrieving a MemberInfo object from below a VTableInterface object can also modify the MemberInfo.


ParameterInfo Object

Members

A ParameterInfo object holds information about a specific parameter of a member function. ParameterInfo objects are retrieved from the Parameters collection of the MemberInfo object.

Property

Type of Information
Name | What is the parameter name? (may be an empty string)
VarTypeInfo | What is the parameter type?
Optional, Default, DefaultValue | Is this parameter required? Does it have a default value?
Flags | What are the marshalling settings? (in,out,retval)
CustomDataCollection,HasCustomData | Is there CustomData for this parameter?


SearchHelper Object and Members

CheckHaveMatch(ByVal Name As String) As Boolean

The SearchHelper Object and the CheckHaveMatch method are used by the GetMembersWithSubString method to track name hits across multiple libraries. Note that the GetMembersWithSubStringEx method does not require an explicit SearchHelper object when called multiple times, so this object is no longer required for cross library member searches. However, you could still use it for your own purposes.

A SearchHelper object can be created either with the New keyword, or with the CreateObject and the TLI.SearchHelper ProgID.

A SearchHelper instance is used by passing CheckHaveMatch a Name. If CheckHaveMatch has already been called with the same name, then it returns True. Otherwise, it adds the name to its internal hash table and returns False.

The SearchHelper Object also has a hidden Init method which is obsolete and does absolutely nothing. It is included only for compatibility with earlier TLI versions.


SearchItem Object

Members

A single item in a SearchResults collection. Besides Name (the default property) and NamePtrW, the properties supported by a SearchItem object depend on the method which returned the SearchResults collection. If a property is not supported, it raises error tliErrNotApplicable.

Property

Source Methods
Constant Applies To
Hidden Applies To
InvokeGroup Applies To
InvokeKinds Applies To
LibNum Applies To
MemberId Applies To
SearchData Applies To
SearchType Applies To
TypeInfoNumber Applies To

SearchItem objects are simply placeholders into a SearchResults collection. This makes them very lightweight, but has inherent limitations. Since a SearchItem has no data without its SearchResults parent collection, a change in the parent collection will invalidate all outstanding SearchItem references which come from that collection. If the parent has changed since a SearchItem object was retrieved, then reading any property will return tliErrSearchResultsChanged.

As a performance enhancement, the memory for the first two SearchItem objects is allocated with a SearchResults collection. Therefore, if you never have more than 2 SearchItem references outstanding on a given SearchResults collection, walking the collection requires no memory allocation, making it very fast. Since a SearchItem object is very cheap to generate, especially if no more than 2 are outstanding from a given collection, and is easily zombied, there is no reason to cache these objects. If you must cache an item, cache the 1-based Index of the item in the collection instead of the object itself, and fetch a new reference as needed from the SearchResults collection.


TLIApplication Object

Members

TLIApplication is the top level application object for the TLI object model. As an application object, you never actually have to type TLIApplication in VB: all of the properties and methods on TLIApplication are accessible globally or with a TLI qualifier, and the object instantiates automatically. To remove TlbInf32.dll from memory, be sure to explicitly Set TLIApplication = Nothing to force VB to release the application object reference. You can also create a TLIApplication object using CreateObject with the "TLI.TLIApplication" progid.

TLIApplication methods and properties break down into five different categories:

  • Create new TypeLibInfo objects (TypeLibInfoFromFile, TypeLibInfoFromRegistry, and TypeLibInfoFromITypeLib)

  • Create new TypeInfo objects (InterfaceInfoFromObject, ClassInfoFromObject, TypeInfoFromITypeInfo)

  • Manipulate running IDispatch-based objects (Invoke* Methods and Properties)

  • Examine and modify Variants containing records (TypeInfoFromFromRecordVariant, RecordField)

  • Modify global settings (ResolveAliases, ListBoxNotification)


TypeInfo Object and Specific Types

TypeInfo Object and Specific TypeInfo Types

See Also Members

A TypeInfo is the main building block for a type library. Therefore, the TypeInfo object/TypeInfos collection lie just below the TypeLibInfo object in the TLI object hierarchy. Since there are different varieties of TypeInfo objects (categorized by TypeKind), there are also different types of TypeInfo objects in TLI.

The TypeInfo object supports the superset of all the properties and methods available for TypeInfos of any TypeKind, while the remaining types (CoClassInfo, ConstantInfo, DeclarationInfo, InterfaceInfo, IntrinsicAliasInfo, RecordInfo, UnionInfo) support only those properties and methods which are applicable to the given type. For more information on how the TypeInfos are grouped into collections, see TypeInfos.

Any specifically typed TypeInfo object can be assigned to a TypeInfo object variable, but calling a member function not supported by the specific type will cause a tliErrIncompatibleTypeKind error. TypeInfo objects are retrieved from the TypeInfos collections using accessor functions.

Methods and properties which are not supported by all TypeInfo type objects are shown here:

  • GetMember and Members are not supported by the CoClassInfo and IntrinsicAliasInfo objects.

  • DefaultInterface and DefaultEventInterface are supported only by a CoClassInfo type object. To use GetMember and Members on a CoClassInfo type object, you must first access an interface using these properties or the Interfaces collection.

  • VTableInterface is supported only by an InterfaceInfo type object (see note on DeclarationInfo and VTableInterface in VTableInterface topic).

  • Interfaces applies only to CoClassInfo, while ImpliedInterfaces implies only to InterfaceInfo. (ImpliedInterfaces is called Interfaces on a TypeInfo object).


TypeLibInfo Object

Members

The TypeLibInfo object is the central object in the TLI object model hierarchy. A TypeLibInfo object represents a type library. TypeLibInfo objects can be created with the New keyword or with CreateObject and the "TLI.TypeLibInfo" progid. The members of TypeLibInfo fall into several different categories.

  • Properties and Methods used to load a type library into the TypeLibInfo object. A newly created TypeLibInfo object requires a type library to be loaded before it can do much. Applicable Members

  • Information about the type library itself. Applicable Members

  • Various TypeInfos collections.

  • Methods returning SearchResults objects. This group of methods opens the door to the primary benefit of using TLI objects in that they automatically group and filter the raw data available from the TypeInfos collections and TypeInfo objects and put it in usuable form. Many of these methods also have *Direct counterparts, which are used to place data directly into a Windows ListBox or ComboBox. Applicable Members

  • Settings which modify or otherwise relate to the SearchResults collections returned by the methods in the previous group. Applicable Members


VarTypeInfo Object, VarTypeInfo and ReturnType Properties

Members of VarTypeInfo Properties Apply To

The VarTypeInfo object is used to represent the type of a parameter, or the return type of a function or property. To retrieve the type of a ParameterInfo object, use the VarTypeInfo property. For the return type of a MemberInfo object, use the ReturnType property.

The VarTypeInfo object is used to represent both intrinsic types (Long, Integer, String, etc.) and type library defined types (OLE_COLOR alias, Picture class, VbVarType enum, GUID structure, etc). The VarType property is used to determine if the object is an intrinsic type, a type library defined type, or an array of intrinsic or defined types. Be sure to set the ResolveAliases property to the desired setting before retrieving VarTypeInfo objects.

As shown in the sample below, the VarType and TypedVariant properties are sufficient for describing the type on an intrinsic VarTypeInfo object, but the TypeInfo and related properties are required to get information about types defined in type libraries. For other types of information, use the ArrayBounds method to get bounds on fixed-size (VT_VECTOR) arrays, and the PointerLevel and ElementPointerLevel properties to determine if a type requires dereferencing (ByVal/ByRef information).

Example: Print the type represented by a VarTypeInfo Object

Dim VTInfo As VarTypeInfo
Dim VT As Integer
Dim VTBase As Integer
With VTInfo
    VT = .VarType
    If VT And VT_ARRAY Then
        Debug.Print "Array of ",
    ElseIf VT And VT_VECTOR Then
        Debug.Print "Fixed size array of ",
    End If
    VTBase = VT And Not (VT_ARRAY Or VT_VECTOR)
    If VTBase Then
        Debug.Print TypeName(.TypedVariant)
    Else
        On Error Resume Next
        Debug.Print .TypeInfo.Name
        If Err Then
            Debug.Print "<Unregistered External Type>"
        End If
        On Error GoTo 0
    End If
End With


Filter Method, CustomFilter Interface, TliCustomFilterAction Enum

Applies To

Filter(ByVal CustomFilter As CustomFilter, _
  Optional AppendExtractedTo As SearchResults, _
  Optional ByVal StartAfter As SearchItem) As SearchResults
Private Sub CustomFilter_Visit ( _
   ByVal Item As SearchItem, Action As TliCustomFilterAction)
Enum TliCustomFilterAction
  tliCfaLeave,
  tliCfaDuplicate,
  tliCfaExtract,
  tliCfaDelete
End Enum

The Filter method is used to modify an existing SearchResults collection, or to create new SearchResults collections based solely on data from an existing collection. The Filter method has one required parameter, CustomFilter, which takes a reference which implements the CustomFilter interface. Filter then calls the implemented Visit method one time for each item in the collection, passing in a SearchItem object, and expecting an Action value in return. There are four actions which you can tell TLI to take on the SearchItem object. In the following table, calling collection means the SearchResults collection on which the Filter method was called, and returned collection means the SearchResults collection returned by the Filter method.

Action | Description
tliCfaLeave | Do nothing to Item (default on each Visit call)
tliCfaDuplicate | Make a copy of Item and place in the returned collection
tliCfaExtract | Remove Item from the calling collection and place in the returned collection
tliCfaDelete | Delete outright from the calling collection

Example: In a VB form, split the properties and methods of the SearchResults collection into two different collections.

Implements CustomFilter

Private Sub CustomFilter_Visit( _
  ByVal Item As TLI.SearchItem, Action As TLI.TliCustomFilterAction)
  If Item.InvokeKinds = INVOKE_FUNC Then Action = tliCfaExtract
End Sub

Private Sub Form_Load()
Dim SRProps As SearchResults
Dim SRMethods As SearchResults
Dim SI As SearchItem
With TLI.TypeLibInfoFromFile("tlbinf32.dll")
  With .GetMembers(.MakeSearchData("SearchResults", tliStClasses))
    'Extract methods
    Set SRMethods = .Filter(Me)
    'Only Properties are left in original collection
    'Note: Me and .Me are different. Me is the form, .Me is the object
    'in the enclosing With statement (supported by all TLI objects)
    Set SRProps = .Me
  End With
End With

'Display results
Debug.Print "**Properties**"
For Each SI In SRProps
  Debug.Print SI
Next
Debug.Print "**Methods**"
For Each SI In SRMethods
  Debug.Print SI
Next
End Sub

Output:
**Properties**
Count
Item
Sorted
**Methods**
Filter
Locate
Sort

The optional AppendExtractedTo parameter of the Filter method specifies a SearchResults collection to which TLI will append any items with a returned action of tliCfaExtract or tliCfaDuplicate. This lets you pull data from several SearchResults collections into a single collection. If the AppendExtractedTo and calling collections do not hold the same type of data, Filter will raise error tliErrIncompatibleData. As an example of using this parameter, add the line SRMethods.Filter Me, SRProps before displaying data in the previous example. This empties the SRMethods collections and places all methods at the end of the SRProps collection.

You can stop the Filter method at any time by raising the untrapped tliErrStopFiltering error from the Visit method (Err.Raise tliErrStopFiltering). The Filter method will succeed, but no further items will be sent to Visit.

The optional StartAfter parameter specifies an alternate starting position for the Filter method. The SearchItem object passed to StartAfter must be retrieved directly from the calling collection. Due to internal design limitations, the Item parameters passed to the Visit method are not considered to have been retrieved directly. If you cache an Item parameter and try to use it as a future StartAfter object, Filter will raise tliErrIncompatibleData. As an alternate mechanism, simply increment a counter when Visit is called to maintain the Index of the passed in SearchItem in the calling collection.


Sort Method, CustomSort Interface

Sort Method; CustomSort Interface

Applies To

Sort(Optional ByVal CustomSort As CustomSort)
Private Sub CustomSort_Compare( _
  ByVal Item1 As SearchItem, ByVal Item2 As SearchItem, Compare As Long)

Use the Sort method to sort a SearchResults collection. SearchResults collections are sorted by default, but this initial sort can be turned off using the Sort parameter for most of the methods which return SearchResults collections. If you're appending collections using a StartResults parameter, then it is most efficient to call the Sort method once after the collection is finalized instead of doing an implicit sort multiple times. Note that because of the size of a SearchResults collection returned by GetMembersWithSubStringEx, avoid sorting the collection altogether if possible. Sorting a GetMembersWithSubStringEx collection is also an additional memory hit.

The default sort order is alphabetical, except with a GetMembersWithSubStringEx collection, where the InvokeGroup is the primary sort key.

To apply a custom order to your SearchResults collection, call the Sort method with the optional CustomSort parameter specified. If you're familiar with a standard qsort callback function, then CustomSort_Compare should look very familiar to you. The Sort method will call CustomSort_Compare multiple times, passing in two SearchItem objects. Set the Compare parameter based on the following table:

Condition

Compare
Item1 < Item2 | < 0
Item1 = Item2 | 0
Item1 > Item2 | > 0

The CustomSort interface is also used with the Locate method, in which case Item2 will always be Nothing. In this case Compare should use the above table as if the searched for data were in Item2.


ListBoxNotification Interface, Property

Applies To

ListBoxNotification As ListBoxNotification
Private Sub ListBoxNotification_OnAddString( _
  ByVal lpstr As Long, ByVal fUnicode As Boolean)

You can implement the ListBoxNotification interface if you want to be notified when a new string is added to an hWnd specified in a *Direct call. The ListBoxNotification interface has one member, OnAddString, which is called whenever a new item is added to the ListBox or ComboBox. The ListBoxNotification property on the TLIApplication object is a global setting which should be set immediately before a *Direct call, and set to Nothing immediately afterwards.

OnAddString is called before an item is added and is generally used for two things. The first is for clearing a list during a search. As an example, before executing GetTypesWithSubString, you don't know if the search will actually result in a hit. ListBoxNotification lets you defer emptying your window until the first string is added, so you don't have a zero hit. The second reason to use ListBoxNotification is to calculate the size for a horizontal scrollbar without rewalking the entire list after it is filled. The lpstr parameter is a pointer to a string. If the system supports UNICODE API's (Windows NT), then lpstr will be a UNICODE string and fUnicode will be True. Otherwise, lpstr is an ANSI string.

Example: OnAddString sample implementation

'Note: The API and class details are left up to the reader
Implements ListBoxNotification
Private Sub ListBoxNotification_OnAddString( _
  ByVal lpstr As Long, ByVal fUnicode As Boolean)
Dim Size As POINTAPI
Dim NewMax As Integer
  If m_fClearOnAddString Then
    Clear
    m_fClearOnAddString = False
  End If
  If fUnicode Then
    GetTextExtentPoint32W m_hDC, lpstr, lstrlenW(lpstr), Size
  Else
    GetTextExtentPoint32A m_hDC, lpstr, lstrlenA(lpstr), Size
  End If
  NewMax = Size.X + m_Extra
  If NewMax > m_HorizontalExtent Then m_HorizontalExtent = NewMax
End Sub


AddTypes[Direct] Method

Applies To

Function AddTypes(
  TypeInfoNumbers() As Integer,
  Optional StartResults As SearchResults,
  Optional ByVal SearchType As TliSearchTypes = tliStDefault,
  Optional ByVal Sort As Boolean = True) As SearchResults
Function AddTypesDirect(
  TypeInfoNumbers() As Integer,
  ByVal hWnd As Long,
  Optional ByVal WindowType As TliWindowTypes = tliWtListBox,
  Optional ByVal SearchType As TliSearchTypes = tliStDefault) As SearchResults

The AddTypes method is used append to or generate a SearchResults collection which contains arbitrary types. Generally, you can retrieve the set of types you want directly using the GetTypes, GetTypesWithSubString, GetTypesWithMember, and GetTypesWithMemberEx functions. However, if you wish to add additional types to these collections or start a collection from scratch, then you can use the AddTypes method. To add types to a SearchResults collection, simply specify 1 or more TypeInfoNumbers and a SearchType. A SearchItem object will be added to the collection for each TypeInfoNumber which satisfies the specified SearchType and the current SearchCriteria.

Using the StartResults parameter, you can append types to an existing collection. StartResults allows you to retrieve types multiple times from the same TypeLibInfo object, or from multiple libraries. You can distinguish between different libraries by setting the LibNum property before calling AddTypes. If you're placing results from multiple AddTypes calls in a single collection, set the Sort parameter to false and call the Sort method after the last library has contributed its data.

The AddTypesDirect method generates the same data as AddTypes, except the results are placed directly in a ListBox or ComboBox as specified by the hWnd and WindowType parameters. SearchData is placed in the ItemData field. The data will be sorted if the ListBox/ComboBox has a sorted style and placed at the end of the list otherwise.

Example: Using AddTypes to create a SearchResults collection which contains all of the implemented interfaces of a coclass. Since this collection may span multiple libraries, a VBA Collection is returned which contains TypeLibInfo objects indexed by the LibNum of the items in the returned collection.

Function ImplementedInterfaces( _
  ByVal CCInfo As CoClassInfo, _
  Libs As Collection, _
  Optional ByVal fIncludeDefault As Boolean = True) As SearchResults
Dim SR As SearchResults
Dim IFace As InterfaceInfo
Dim TLInf As TypeLibInfo
Dim TLInfLast As TypeLibInfo
Dim strKey As String
Dim TypeInfos(0) As Integer
Dim tinfoDefault As IUnknown
Dim fLookupLib As Boolean
  Set Libs = New Collection
  If Not fIncludeDefault Then
    Set tinfoDefault = CCInfo.DefaultInterface.ITypeInfo
  End If
  On Error GoTo Error
  For Each IFace In CCInfo.Interfaces
    If 0 = (IFace.AttributeMask And _
            (IMPLTYPEFLAG_FSOURCE Or IMPLTYPEFLAG_FRESTRICTED)) Then
      If Not fIncludeDefault Then
        If tinfoDefault Is IFace.ITypeInfo Then
          'Turn off default check once we find it
          fIncludeDefault = True
          GoTo DoNext
        End If
      End If
      Set TLInf = IFace.Parent
      TypeInfos(0) = IFace.TypeInfoNumber
      fLookupLib = True
      If TLInfLast Is Nothing Then
      ElseIf TLInf.IsSameLibrary(TLInfLast) Then
        'TLInfLast is simply an optimization.
        'Checking IsSameLibrary is faster than
        'doing a collection lookup.
        fLookupLib = False
        'Use the TypeLibInfo object from the
        'collection so that it has the LibNum set
        Set TLInf = TLInfLast
      End If
If fLookupLib Then
        strKey = CStr(ObjPtr(TLInf.ITypeLib))
        On Error Resume Next
        'Use the TypeLibInfo object from the
        'collection so that it has the LibNum set
        Set TLInf = Libs(strKey)
        If Err Then
          'New library
          TLInf.LibNum = Libs.Count + 1
          Libs.Add TLInf, strKey
          Set TLInfLast = TLInf
        End If
        On Error GoTo Error
      End If
      'Call AddTypes, appending to the previous collection
      Set ImplementedInterfaces = _
       TLInf.AddTypes(TypeInfos, ImplementedInterfaces, , False)
    End If
DoNext:
  Next
  Exit Function
Error:
  Resume DoNext
End Function

'Calling Code
Dim TLInf As TypeLibInfo
Dim SR As SearchResults
Dim SI As SearchItem
Dim Libs As Collection
Dim SRMembers As SearchResults
Set SR = ImplementedInterfaces(CCInfo, Libs)
If Not SR Is Nothing Then
  SR.Sort
  For Each SI In SR
    'Do a set first to avoid late bound calls
    'against TLI objects
    Set TLInf = Libs(SI.LibNum)
    Set SRMembers = TLInf.GetMembers(SI.SearchData)
    'Process members
  Next
End If


AppObjString Property

Applies To

AppObjString As String

If a class is marked as an application object, then the class can be auto-instantiated and members of the class can be called without qualification in VB. In order to get a list of methods and properties which can be called without qualification, simply set the AppObjString on the TypeLibInfo object. Now, GetTypes, GetTypesWithMember, and GetTypesWithMemberEx will add an item to the returned SearchResults collection with the name of the AppObjString. Setting this property will have an effect only if the requested SearchType includes tliStClasses. Items returned with the AppObjString string will have a SearchType of tliStAppObject.

With the exception of the MakeSearchData, method, tliStAppObject should not be passed into a SearchType parameter. The appobject class may be visible under its normal name as well as under the AppObjString. GetMembers will return the same collection for an appobject SearchData as for normal class of the same type, except that no events are included. Since it is standard practice to have only one appobject class in a type library, TLI makes no attempt to check for multiple appobjects. If this condition does occur, then AppObjString will be returned multiple times in the same SearchResults collection. However, if you're placing multiple type libraries in the same SearchResults collection, then you can set the ShowLibName property to distinguish between application level methods and properties in the different libraries.

Example: Using the AppObjString against the TLI library

Dim SI As SearchItem
Dim TLInf As TypeLibInfo
Set TLInf = TLI.TypeLibInfoFromFile("tlbinf32.dll")
TLInf.AppObjString = "<Unqualified>"
For Each SI In TLInf.GetTypesWithMember("InvokeHook", , tliStClasses)
  Debug.Print SI.Name, SI.SearchType
Next

Output:
<Unqualified>     16
TLIApplication    1


ArrayBounds Method

Applies To

ArrayBounds(Bounds() As Long) As Integer

The ArrayBounds method of the VarTypeInfo object retrieves a 2 column array in the first parameter and returns the number of dimensions in the array. Bounds arrays are 1 based and have the lower bound in the first column and the upper bound in the second. ArrayBounds is valid only for VarTypeInfo objects where the VarType contains VT_VECTOR. Attempting to call ArrayBounds for other types will return errors tliErrTypeNotArray or tliErrArrayBoundsNotAvailable.

Example: Print bounds where array has bounds SomeArray(1 To 10, 5 To 15):

Dim Bounds() As Long
Dim VTInfo As VarTypeInfo
Dim i As Integer
If VTInfo.VarType And VT_VECTOR Then
  For i = 1 To VTInfo.ArrayBounds(Bounds)
    Debug.Print Bounds(i, 1), Bounds(i, 2)
  Next i
End If

Output:
1    10
5    15

Bug alert and fix:

The ArrayBounds function in the VB6.0 TlbInf32.Dll (file version 1.1.8169) returns incorrect information for the upper bounds of the array. Don't use ArrayBounds directly against this Dll since this bug will be fixed in future releases. Instead, call FixArrayBounds(VTInfo, Bounds) with the function shown below.

Private m_fCheckedTLIArrayBounds As Boolean
Private m_fFixArrayBounds As Boolean
Function FixArrayBounds(VTInfo As VarTypeInfo, Bounds() As Long) As Integer
Dim Dims As Integer
  If Not m_fCheckedTLIArrayBounds Then CheckTLIArrayBounds
  FixArrayBounds = VTInfo.ArrayBounds(Bounds)
  If m_fFixArrayBounds Then
    For Dims = 1 To FixArrayBounds
      Bounds(Dims, 2) = Bounds(Dims, 2) + 2 * Bounds(Dims, 1) - 1
    Next
  End If
End Function
Private Sub CheckTLIArrayBounds()
Dim Bounds() As Long
  Debug.Assert Not m_fCheckedTLIArrayBounds
  On Error Resume Next
  TLI.TypeLibInfoFromFile("stdole2.tlb").TypeInfos. _
  .NamedItem("GUID").Members(4).ReturnType.ArrayBounds Bounds
  If Bounds(1, 2) = 8 Then m_fFixArrayBounds = True
  m_fCheckedTLIArrayBounds = True
End Sub


AttributeMask Property and Associated Enums

AttributeMask Property; LibFlags, TypeFlags, ImplTypeFlags, FuncFlags, VarFlags Enums

Applies To

AttributeMask As Integer

The AttributeMask property returns miscellaneous attribute information about TypeLibInfo, TypeInfo, and MemberInfo objects. The type of information returns depends on the type of object as well as other factors. The enums used to retrieve these values are straight copies of the corresponding enums as defined in the OLE Automation headers. To get string versions of these attributes, use the AttributeStrings method.

Enum Name | Object Type | Other Information
LibFlags | TypeLibInfo |
ImplTypeFlags | InterfaceInfo | Object obtained through Interfaces, DefaultInterface, or DefaultEventInterface on a CoClassInfo object
TypeFlags | TypeInfo | Object obtained any way not specified for ImplTypeFlags
FuncFlags | MemberInfo | Object has DescKind of DESCKIND_FUNCDESC
VarFlags | MemberInfo | Object has DescKind of DESCKIND_VARDESC


AttributeStrings Method

Applies To

AttributeStrings(AttributeArray() As String) As Integer

The AttributeStrings method retrieves the string forms of the flags returned by the AttributeMask property on the same object. Strings are returned as they appear in ODL (object description language) syntax.

Example: Print attributes as strings

Dim TI As TypeInfo
Dim Attributes() As String
Dim i As Integer
    Set TI = TypeLibInfoFromFile("dao350.dll"). _
             GetTypeInfo("DBEngine")
    For i = 1 To TI.AttributeStrings(Attributes)
        Debug.Print Attributes(i)
    Next i

Output:
appobject
licensed
hidden

In addition to the AttributeStrings method, there are also five hidden functions which are available if TlbInf32.dll is on the path (the default install is the System32 directory, so this is true in general). GetFunctionAttributeStrings, GetImplAttributeStrings, GetLibraryAttributeStrings, GetTypeInfoAttributeStrings, and GetVariableAttributeStrings can be used to translate data from an AttributeMask directly into string form. These can also be used with the special TypeFlags values which give all allowable flags for each TypeKind.

Example: Print strings directly from attribute mask

For i = 1 To _
  GetTypeInfoAttributeStrings(TYPEFLAG_COCLASSATTRIBUTES, Attributes)
  Debug.Print Attributes(i)
Next i

Output:
appobject
licensed
hidden
predeclid
control
restricted
aggregatable
replaceable


BestEquivalentType Property

Applies To

BestEquivalentType(ByVal TypeInfoName As String) As String

Frequently, a type library will have types which are not generally displayed in object browsers. For example, the default interface of a TypeInfo with a TypeKind of TKIND_COCLASS is not included in a SearchResults collection returned by GetTypes. However, these types can be displayed via the VarTypeInfo object while enumerating members and properties.

Given a TypeInfoName, BestEquivalent type will simply return the input parameter if that type is best, or it will return a better equivalent type. For the default interface of a coclass, the coclass is returned. For a hidden type with a visible alias, the alias is returned. For a hidden type with a visible equivalent, the visible type is returned. For example, in the msrdo20.dll type library, the rdoConnections.Item method returns a type of _rdoConnection, which isn't shown in the GetTypes list because it is the default interface of the rdoConnection coclass. So BestEquivalentType("_rdoConnection") returns "rdoConnection", which can be located in the GetTypes collection.


CallConv Property, CallConvs Enum

CallConv Property; CallConvs Enum

Applies To

CallConv As CallConvs

For a MemberInfo object with a DescKind of DESCKIND_FUNCDESC, the CallConv property returns the calling convention for the function. The most common value returned is CC_STDCALL. The MemberInfo must be retrieved from the Members collection or CallConv will raise error tliErrDataNotAvailable. CallConv will always return CC_MAX for a a DESCKIND_VARDESC MemberInfo. The CallConvs enum corresponds to CALLCONV as defined in the OLE Automation headers.


CaseTypeName, CaseMemberName Methods

Applies To

Function CaseTypeName(
  bstrName As String,
  Optional ByVal SearchType As TliSearchTypes = tliStDefault) As TliSearchTypes
Function CaseMemberName(
  bstrName As String,
  Optional ByVal SearchType As TliSearchTypes = tliStDefault) As Boolean

The CaseTypeName and CaseMemberName methods of the TypeLibInfo object are fast lookups to see if a given name is contained in a type library, and to modify the string to match the casing in the type library. For both methods, the SearchType parameter determines which set of types are to be considered for casing.

CaseTypeName returns a TliSearchTypes which indicates which of the requested SearchTypes actually generated a match. If the return value is 0, then no match was generated among the requested types.

Example: Calling CaseTypeName

Dim Name As String
With TLI.TypeLibInfoFromFile("tlbinf32.dll")
  Name = "typelibinfo"
  Debug.Print .CaseTypeName(Name, tliStAll), Name
End With

Output:
1    TypeLibInfo

CaseMemberName takes the same input parameters as CaseTypeName. For performance reasons, CaseMemberName requests only the first type with the given member and checks that type against the requested SearchTypes. Although the case is rare, if a library contains types which fall under different SearchTypes categories but have a member of the same name, then CaseMemberName might give a false negative if SearchTypes is restricted to something other than tliStAll. As only the first retrieved type is examined, and no attempt is made to retrieve other types, a reliable value for the matching SearchTypes can't be determined as in the CaseTypeName method. Therefore, the return value for CaseMemberName has type Boolean instead of TliSearchTypes.

For both of Case*Name methods, the bstrName parameter may be cased differently after the call even if the return value indicates that a match wasn't found. A casing change indicates that the name is recognized somewhere in the type library, but either isn't a type or member as requested, or doesn't match the SearchTypes parameter and current SearchCriteria settings.

Example: A TextBox control Change event which cases member names for a TypeLibInfo object (m_TLInf)

Private Sub Text1_Change()
Dim strTmp As String
Dim iCurSelStart As Integer
Dim iCurSelLength As Integer
Static fStayOut As Boolean
  If fStayOut Then Exit Sub
  With Text1
    strTmp = .Text
    If Len(strTmp) Then
      iCurSelStart = .SelStart
      iCurSelLength = .SelLength
      fStayOut = True
      If m_TLInf.CaseMemberName(strTmp, tliStAll) Then
        .Text = strTmp
      Else
        .Text = LCase$(strTmp)
      End If
      .SelStart = iCurSelStart
      .SelLength = iCurSelLength
      fStayOut = False
    End If
  End With
End Sub


InterfaceInfoFromObject, ClassInfoFromObject Methods

Applies To

InterfaceInfoFromObject(ByVal Object As Object) As InterfaceInfo
ClassInfoFromObject(ByVal Object As IUnknown) As TypeInfo

TypeInfo objects are generally retreived from a TypeLibInfo object. However, this also available directly from running objects. The InterfaceInfoFromObject and ClassInfoFromObject methods allow you to inspect a running object, retrieving information about its properties, methods, and events. Once you have information about its properties and methods, you can then use the Invoke functionality to manipulate the object. With both object inspection and Invoke support, TLI allows you to program against dynamic objects.

InterfaceInfoFromObject and ClassInfoFromObject correspond to two different ways in which objects can provide type information. InterfaceInfoFromObject takes an IDispatch object (Object in VB) and calls IDispatch::GetTypeInfo. This returns an InterfaceInfo type TypeInfo object from which you can get property and method information. ClassInfoFromObject takes any object, retrieves the IProvideClassInfo interface, and calls the GetClassInfo method. The result object is supposed to have a TypeKind of TKIND_COCLASS, but this is dependent on the implementation of the object, so ClassInfoFromObject returns a generic TypeInfo type instead of a CoClassInfo.

While InterfaceInfoFromObject returns you information about the currently referenced interface only, ClassInfoFromObject returns the coclass information, which means that you can retrieve information about all events and other supported interfaces, as well as the properties and methods of the current interface.

Any given object may support 0, 1, or 2 of these methods, so you should always use error trapping when attempting to do object inspection. For example, a private VB class in a built executable doesn't support object inspection. All public objects in a VB server support InterfaceInfoFromObject, while only creatable classes (or classes with events) support ClassInfoFromObject.

Some objects implementations will actually implement an ITypeInfo interface in memory. However, most objects just use type information provided by some on-disk type library. This means that you can usually get information for not only the running object, but all objects in its type library. Use the Parent property to retrieve the TypeLibInfo object. If the object being inspected is actually running in a different thread, process, or machine (via DCOM) than your code, then object inspection will be much faster if you can load the type library in the same thread.

Example: Retrieving class information, using a local type library if available.

Function BestClassInfo(ByVal Object As Object) As TypeInfo
  Set BestClassInfo = TLI.ClassInfoFromObject(Object)
  On Error GoTo NotAvailable
  With BestClassInfo.Parent
    With TLI.TypeLibInfoFromRegistry _
         (.GUID, .MajorVersion, .MinorVersion, .LCID)
      Set BestClassInfo = .Me.TypeInfos.IndexedItem(BestClassInfo.TypeInfoNumber)
    End With
  End With
  Exit Function
NotAvailable:
  Err.Clear
End Function


Constant Property

Applies To

Constant As Boolean

Indicates whether a SearchItem object is a constant. To retrieve the value of the constant, use the Value property on the MemberInfo object returned by the GetMemberInfo method. You can also test if an item is constant by testing the InvokeKinds property against INVOKE_CONST.

Retrieving the Constant property from SearchResults collection items returned from methods which are not in the Applies To list will raise error tliErrNotApplicable.


ContainingFile Property, TypeLibInfoFromFile Method

Applies To

ContainingFile As String
TypeLibInfoFromFile(ByVal FileName As String) As TypeLibInfo

The ContainingFile property of a TypeLibInfo object sets or returns the file which contains the type library resource which is currently being represented. Type libraries can be either standalone files, which have the extension TLB, or contained as resources in other files (EXE, DLL, OCX, OLB, etc). By default, type libraries are loaded from resources 1. To load the type library from an alternate resources, append \#. For example, setting ContainingFile to "msvbvm60.dll\3" will load the type library at resource 3. ContainingFile can raise error tliErrCantLoadLibrary.

TLI.TypeLibInfoFromFile is used to create a TypeLibInfo object directly from a file and is equivalent to creating a New TypeLibInfo object and then setting the ContainingFile property.

The ContainingFile property is read-write and can be set at any time to switch the type library being viewed by the TypeLibInfo instance. The ContainingFile property, the LoadRegTypeLib method, and the ITypeLib property—together with the corresponding globally accessible TLIApplication methods—are the only ways to load a type library into a TypeLibInfo object. If a valid type library isn't loaded, most other TypeLibInfo member functions will return tliErrNoCurrentTypelib.


Count Property

Applies To

'SearchResults collection
Count As Long
'Other collections
Count As Integer

The Count property specifies the number of items in a TLI collection. All TLI collections are 1-based, so valid Index values for the Item property (the default method of all TLI collections) are 1 to Count. Note that Count for the Members and Parameters collections may be dependent on the VTableInterface setting used when the collection was retrieved.


Optional and Default Parameters

Applies To

'ParameterInfo Object
Optional As Boolean
Default As Boolean
DefaultValue As Variant

'Parameters Collection
OptionalCount As Integer
DefaultCount As Integer

A ParameterInfo object can be required, default, or optional. If Optional is True, then the parameter is an optional parameter as originally introduced in the VB4 timeframe, which is a Variant without a default value specified. If Default is True, then the parameter has a default value, returned by the DefaultValue property, and can have a type other than Variant. The Optional and Default flags are mutually exclusive in TLI.

'A function with 1 required, 1 default, and 1 optional parameter
Sub Foo(x As Integer, Optional y As String = "Default", Optional z)

The OptionalCount and DefaultCount values on the Parameters collection give a count of the total number of Optional and Default parameters. The exception here is that an OptionalCount of –1 indicates that the final parameter is a ParamArray.

Dim RequiredCount As Integer
Dim Params As Parameters
With Params
  If .OptionalCount = -1 Then
    RequiredCount = .Count - .DefaultCount
  Else
    RequiredCount = .Count - .DefaultCount - .OptionalCount
  End If
End With

The DefaultValue property returns a Variant which corresponds to the VarType of the parameter. This value is often redundant as it may be the default value for the given type. For example the '= 0' in 'Optional x As Long = 0' isn't needed. The ProduceDefaultValue routine will produce a default value string only if DefaultValue isn't the default for its type. For an enum, it will locate the first item which corresponds to the given name.

'Calling code
With ParameterInfo
  If .Default Then
    Debug.Print ProduceDefaultValue(.DefaultValue, .VarTypeInfo.TypeInfo)
  End If
End With

Private Function ProduceDefaultValue(DefVal As Variant, ByVal TI As TypeInfo) As String
Dim lTrackVal As Long
Dim MI As MemberInfo
Dim TKind As TypeKinds
    If TI Is Nothing Then
        Select Case VarType(DefVal)
            Case vbString
                If Len(DefVal) Then
                    ProduceDefaultValue = """" & DefVal & """"
                End If
            Case vbBoolean 'Always show for Boolean
                ProduceDefaultValue = DefVal
            Case vbDate
                If DefVal Then
                    ProduceDefaultValue = "#" & DefVal & "#"
                End If
            Case Else 'Numeric Values
                If DefVal <> 0 Then
                    ProduceDefaultValue = DefVal
                End If
        End Select
    Else
        'See if we have an enum and track the matching member
        'If the type is an object, then there will never be a
        'default value other than Nothing
        TKind = TI.TypeKind
        Do While TKind = TKIND_ALIAS
            TKind = TKIND_MAX
            On Error Resume Next
            Set TI = TI.ResolvedType
            If Err = 0 Then TKind = TI.TypeKind
            On Error GoTo 0
        Loop
        If TI.TypeKind = TKIND_ENUM Then
            lTrackVal = DefVal
            For Each MI In TI.Members
                If MI.Value = lTrackVal Then
                    ProduceDefaultValue = MI.Name
                    Exit For
                End If
            Next
        End If
    End If
End Function


DefaultInterface, DefaultEventInterface Properties

Applies To

DefaultInterface As InterfaceInfo
DefaultEventInterface As InterfaceInfo

For a TKIND_COCLASS type TypeInfo, the DefaultInterface property returns the InterfaceInfo object which describes the properties and methods associated with the object by default. In VB, Dim x As CoClassName actually translates into Dim x As DefaultInterfaceOfCoClassName. A coclass is actually collection of interfaces and has no members, so retrieving the Members collection or using GetMember will raise error tliErrIncompatibleTypeKind. Therefore, it is necessary to first get the DefaultInterface of the coclass before reading the properties and methods.

The DefaultEventInterface is the interface which defines the set of events which are associated by default with the coclass name. To retrieve properties, methods, and events in the same collection, use the GetMembers method.

Both the DefaultInterface and DefaultEventInterface are actually members of the Interfaces collection. To determine which interfaces to use as defaults, TLI walks the interfaces collection and checks the AttributeMask property. DefaultInterface is the first interface with the IMPLTYPEFLAG_FDEFAULT flag set (or the first one without IMPLTYPEFLAG_FSOURCE, if no default is specified). The DefaultEventInterface has IMPLTYPEFLAG_FSOURCE set, and is either the first source interface encountered or the first with the IMPLTYPEFLAG_FDEFAULT or IMPLTYPEFLAG_FDEFAULTVTABLE flags set. For more explicit control over which interface is considered default, you can walk the Interfaces collection in code.


DescKind Property, DescKinds Enum

DescKind Property; DescKinds Enum

Applies To

DescKind As DescKinds

The DescKind property specifies whether a MemberInfo object is defined as a variable/field or as a function. Valid return types DESCKIND_FUNCDESC, DESCKIND_VARDESC, and DESCKIND_NONE. DESCKIND_NONE is returned in error conditions if the DescKind can't be determined. Although all DESCKIND_VARDESC members from a TypeInfo which has a TypeKind of TKIND_INTERFACE or TKIND_DISPATCH are always considered to be properties, not all properties have a DescKind of DESCKIND_VARDESC. A DESCKIND_FUNCDESC member with an INVOKE_PROPERTY* InvokeKind is also considered a property. The DescKinds enum corresponds to the first three members of DESCKIND as defined in the OLE Automation headers. Other DESCKIND values are not applicable to TLI.


ElementPointerLevel Property

Applies To

ElementPointerLevel As Integer

A numeric value indicating the number of levels of indirection required to reach the underlying type of an element of an array type for a VarTypeInfo object. Generally, this will be 0 (ByVal) or 1 (ByRef). However, if the VarType property indicates that the type represented is a TypeInfo and the TypeInfo has TypeKind TKIND_INTERFACE, TKIND_DISPATCH, or TKIND_COCLASS, then 1 is ByVal and 2 is ByRef. For array types (VarType And (VT_ARRAY Or VT_VECTOR) is <> 0), PointerLevel corresponds to the level of indirection to get the array type. This is not the same as the indirection level of the type contained in the array. If the type is not an array, then calling ElementPointerLevel will cause error tliErrTypeNotArray.


Flags Property, ParamFlags Enum

Flags Property; ParamFlags Enum

Applies To

Flags As ParamFlags

The Flags property returns miscellaneous data about a ParameterInfo object. The first 5 ParamFlags values are also defined in the IDLFlags enum and the values are interchangeable. If a ParamFlag is also an IDLFlag, then the setting affects how the item is marshalled. Marshalling occurs when an object is running in a separate thread, process, or machine and a function is called on the object. Data then must be copied across process boundaries, which is an expensive process. IDL settings specify which direction the data is actually copied, as well as some other settings.

Name | Value | IDL | Description
PARAMFLAG_NONE | 0 | x | No data
PARAMFLAG_FIN | 1 | x | When marshalling, data is copied from the caller to the callee. The callee will always receive valid data.
PARAMFLAG_FOUT | 2 | x | Data is copied from the callee to the caller. Can be combined with IN. If IN is not specified, then this type of parameter may be NULL. OUT parameters are always pointer types. When the callee receives the pointer, it is valid or NULL, but *pointer is uninitialized data. The callee must return valid data in *pointer if the function succeeds.
PARAMFLAG_FLCID | 4 | x | A special IN parameter with long type. LCID (language/country identifier information) is automatically passed to this parameter by VB.
PARAMFLAG_FRETVAL | 8 | x | A parameter which is used as the return value for a function. You will only see this value in TLI if a ParameterInfo object is accessed via a VTableInterface style InterfaceInfo. Otherwise, this parameter automatically becomes the ReturnType property of the MemberInfo object.
PARAMFLAG_FOPT | 16 |  | Is the parameter optional? If this is set and FHASDEFAULT is not set, then the Optional property will be True.
PARAMFLAG_FHASDEFAULT | 32 |  | Does the parameter have a default value? If this is set, then FOPT is always set and the Default property will be True.
PARAMFLAG_FHASCUSTDATA | 64 |  | Is CustomData available for the collection. This value is also available through the HasCustomData property.


ResetSearchCriteria, FreeSearchCriteria Methods

Applies To

ResetSearchCriteria(
  Optional ByVal TypeFilter As TypeFlags = TYPEFLAG_DEFAULTFILTER,
  Optional ByVal IncludeEmptyTypes As Boolean = False,
  Optional ByVal ShowUnderscore As Boolean = False)
FreeSearchCriteria()

When you use any methods on a TypeLibInfo object which return SearchResults objects, as well as some of the functions supporting these routines, TLI creates an internal table which maps and categorizes the types in the type library. This table is referred to as the SearchCriteria. If the SearchCriteria isn't built, it is created automatically with the default settings. In order to override the defaults, you need to call ResetSearchCriteria explicitly before using any of the other SearchResults-related functionality.

By default, types with attributes of TYPEFLAG_FRESTRICTED or TYPEFLAG_FHIDDEN aren't included in the SearchResults collections. Type libraries use two different mechanisms to specify that a member is hidden. The first is to set the a hidden bit (TYPEFLAG_FHIDDEN for types), the second is to start the name with an underscore (_) character. In order to include hidden types, set the TypeFilter to TYPEFLAG_FRESTRICTED and the ShowUnderscore parameter to True. Note that this will just get you hidden types. In order to get hidden members as well, use then SetMemberFilters method, and pass True wherever you see a ShowUnderscore parameter.

By default, types with no members don't appear in the returned SearchResults collections. To override this default, call ResetSearchCriteria with the IncludeEmptyTypes parameter set to True.

The SearchCriteria table uses approximately 8 * TypeInfoCount bytes of memory, plus some additional memory for links to external types. To free this memory without releasing the TypeLibInfo object, call FreeSearchCriteria. Since the SearchCriteria is non-trivial to build, use discretion with FreeSearchCriteria so that TLI isn't repeatedly doing the same work.


FuncFilter, VarFilter Properties, SetMemberFilters Method

FuncFilter, VarFilter Properties; SetMemberFilters Method

Applies To

'Members collection
FuncFilter As FuncFlags
VarFilter As VarFlags

'TypeLibInfo object
SetMemberFilters(
   Optional ByVal FuncFilter As FuncFlags = FUNCFLAG_DEFAULTFILTER,
   Optional ByVal VarFilter As VarFlags = VARFLAG_DEFAULTFILTER)

By default, the GetFilteredMembers method of the Members collection removes all hidden and restricted members from the returned SearchResults collection. In order to modify the filters, set the FuncFilter and VarFilter properties before calling GetFilteredMembers. FuncFilter applies to members with a DescKind of DESCKIND_FUNCDESC and VarFilter to DESCKIND_VARDESC members. You will generally have to apply similar flags to both properties [don't cheat, VARFLAG and FUNCFLAG have different values for the same functionality]. A filter value of –1 removes everything.

'Retrieving browsable items from a Members collection
With Members
  .FuncFilter = FUNCFLAG_FRESTRICTED Or FUNCFLAG_FNONBROWSABLE
  .VarFilter = VARFLAG_FRESTRICTED Or VARFLAG_FNONBROWSABLE
  Set SR = GetFilteredMembers
End With

The GetMembers method on the TypeLibInfo object uses the same member filtering defaults as the Members collection. In order to change the defaults, call the SetMemberFilters method. The FuncFilter and VarFilter parameters of SetMemberFilters are analogous with the properties of the same name on the Members collection.


GetDllEntry Method

Applies To

GetDllEntry(DllName As String, EntryName As String, Ordinal As Integer)

If a MemberInfo object describes an entry point in a Dll (synonymous with a VB Declare statement), the GetDllEntry methods retrieves data pertaining to the entry point. If the Dll entry is an ordinal instead of a named entry, then EntryName will return and empty string and Ordinal will contain a valid value.

If the MemberInfo is not an entry point, then GetDllEntry raises error tliErrNotAnEntryPoint. If the MemberInfo object was retrieved by a means other than the Members collection, then this information is not available and the methods raises error tliErrDataNotAvailable.


GetFilteredMembers[Direct] Method

Applies To

GetFilteredMembers(
  Optional ByVal ShowUnderscore As Boolean) As SearchResults
GetFilteredMembersDirect(
  ByVal hWnd As Long,
  Optional ByVal WindowType As TliWindowTypes = tliWtListBox,
  Optional ByVal ItemDataType As TliItemDataTypes = tliIdtMemberID,
  Optional ByVal ShowUnderscore As Boolean = False) As Integer

The GetFilteredMembers method of the Members collection returns a SearchResults collection with members based on the items in the Members collection. The returned collection has the following attributes.

  • Like-named members are combined into a single SearchItem object. The InvokeKinds property can be used to determine how many member functions were compressed into a single object.

  • By default, all hidden and restricted members are removed from the collection. To modify this setting, call the FuncFilter and VarFilter methods before GetFilteredMembers.

  • Unlike the GetMembers method, GetFilteredMembers makes no attempt to retrieve members from a base class. If you want all base members of a class, GetMembers is the recommended method to use. GetMembers also supports properties, methods, and events in the same collection.

See Hidden Property for information on the ShowUnderscore parameter.

The GetFilteredMembersDirect method generates the same data as GetFilteredMembers, except the results are placed directly in a ListBox or ComboBox as specified by the hWnd and WindowType parameters. The ItemDataType parameter determines if the data placed in the ItemData field is the MemberId or the InvokeKinds of the member. tliIdtInvokeKinds is the recommended setting because, unlike InvokeKinds, the MemberId can be regenerated directly from the Name. GetFilteredMembersDirect clears any existing data in the window and always sorts the members, regardless of the sort settings of the ListBox or ComboBox. The value returned from the method indicates the number of items added.


GetMember Property

Applies To

GetMember(ByVal Index As Variant) As MemberInfo

Retrieves a MemberInfo object from a TypeInfo. The Index parameter can be either the Name or MemberId of the requested member. To retrieve MemberInfo object without first obtaining a TypeInfo object, use the GetMemberInfo method.


GetMemberInfo Method

Applies To

GetMemberInfo(
  ByVal SearchData As Long,
  Optional ByVal InvokeKinds As InvokeKinds = INVOKE_UNKNOWN,
  Optional ByVal MemberId As Long = -1,
  Optional ByVal MemberName As String) As MemberInfo

Use the GetMemberInfo method to retrieve a MemberInfo object based solely on data available in SearchResults collections. The SearchData parameter is obtained from the SearchData property or the MakeSearchData method. The InvokeKinds parameter is optional, but should be passed if available to resolve ambiguity when a class contains both a method/property and event with the same name or MemberId. Either MemberId or MemberName must be specified, with MemberId preferred for performance reasons.

Since the MemberId can be retrieved based on the MemberName if InvokeKinds is specified, you should specify tliIdtInvokeKinds instead of tliIdtMemberID when using the GetMembersDirect and GetFilteredMembersDirect methods which support retrieving the InvokeKind. If you're using SearchResults objects from GetMembers* methods, both the InvokeKind and MemberId are readily available, so you don't have to pass the MemberName.


GetMembers[Direct] Method

Applies To

Function GetMembers(
  ByVal SearchData As Long,
  Optional ByVal ShowUnderscore As Boolean = False) As SearchResults
Function GetMembersDirect(
  ByVal SearchData As Long,
  ByVal hWnd As Long,
  Optional ByVal WindowType As TliWindowTypes = tliWtListBox,
  Optional ByVal ItemDataType As TliItemDataTypes = tliIdtMemberID,
  Optional ByVal ShowUnderscore As Boolean = False) As Integer

The GetMembers method of the TypeLibInfo object returns a SearchResults collection with members based on the SearchData property retrieved from a collection created with the *Types* or MakeSearchData methods.

  • Like-named members are combined into a single SearchItem object. The InvokeKinds property can be used to determine how many member functions were compressed into a single object.

  • By default, all hidden and restricted members are removed from the collection. To modify this setting, call SetMemberFilters before GetMembers.

  • If the type specified by SearchData has visible members on a base class, GetMembers automatically retrieves all base members. This is different behavior than the GetFilteredMembers method on the Members collection, which does not walk base classes.

  • If SearchData indicates that an item is a coclass, the SearchType settings used to generate the SearchData determine whether GetMembers returns properties and methods or events or both. Events are marked with an InvokeKinds property of INVOKE_EVENTFUNC, which is a special TLI value for distinguishing events from methods.

See Hidden Property for information on the ShowUnderscore parameter.

The GetMembersDirect method generates the same data as GetMembers, except the results are placed directly in a ListBox or ComboBox as specified by the hWnd and WindowType parameters. The ItemDataType parameter determines if the data placed in the ItemData field is the MemberId or the InvokeKinds of the member. tliIdtInvokeKinds is the recommended setting if you're using the GetMemberInfo method. GetMembersDirect clears any existing data in the window and always sorts the members, regardless of the sort settings of the ListBox or ComboBox. The value returned from the method indicates the number of items added. See SearchData for an example which uses GetMembersDirect.


GetMembersWithSubString[Direct] Method

Applies To

Function GetMembersWithSubString(
  ByVal SubString As String,
  Optional StartResults As SearchResults,
  Optional ByVal SearchType As TliSearchTypes = tliStDefault,
  Optional ByVal SearchMiddle As Boolean = True,
  Optional Helper As SearchHelper,
  Optional ByVal Sort As Boolean = True,
  Optional ByVal ShowUnderscore As Boolean = False) As SearchResults
Function GetMembersWithSubStringDirect(
  ByVal SubString As String,
  ByVal hWnd As Long,
  Optional ByVal WindowType As TliWindowTypes = tliWtListBox,
  Optional ByVal SearchType As TliSearchTypes = tliStDefault,
  Optional ByVal SearchMiddle As Boolean = True,
  Optional Helper As SearchHelper,
  Optional ByVal ShowUnderscore As Boolean = False) As Integer

The GetMembersWithSubString method has been obsoleted by the GetMembersWithSubStringEx method. However, GetMembersWithSubStringEx does not have a corresponding Direct method.

The GetMembersWithSubString method of the TypeLibInfo object is used to retrieve a SearchResults collection with members that contain a given SubString. If SubString is an empty string or vbNullString, this method retrieves all member names. No duplicate names are retrieved. If SearchMiddle is True, then returned collection items will have SubString somewhere in the name of a member. Otherwise, SubString will be found only at the beginning of member names. All searches are case-insensitive.

Since member names are useless information without the ability also display the types to which the member belongs, the GetTypesWithMember method is provided as a companion to GetMembersWithSubString.

The SearchType and Sort parameters are used as described in the GetTypes method. See Hidden Property for information on the ShowUnderscore parameter.

In order to retrieve member names from multiple libraries, you need to use the StartResults and Helper parameters. The SearchHelper object wraps a hash table which tracks which names are already in the collection. In order to maintain information about the contents of the collection, you must create a SearchHelper object before the first call to GetMembersWithSubString and then pass it to the Helper parameter of each call. Note that the GetMembersWithSubStringEx method does not require you to use a SearchHelper object.

Example: Walk a Libs collection to retrieve all names from TypeLibInfo objects

Dim Libs As Collection 'Assume this is filled
Dim TLInf As TypeLibInfo
Dim SRMemberNames As SearchResults
Dim Helper As SearchHelper
Set Helper = New SearchHelper
For Each TLInf In Libs
  Set SRMemberNames = TLInf.GetMembersWithSubString( _
    vbNullString, SRMemberNames, , , Helper, False)
Next
SRMemberNames.Sort

Since a single item in a GetMembersWithSubString SearchResults collection can span a multiple types, multiple InvokeKinds, and multiple libraries, the SearchItem objects in this collection support the Name property only. In order to further divide members into InvokeKinds groups, use the GetMembersWithSubStringEx method.

The GetMembersWithSubStringDirect method generates the same data as GetMembersWithSubString, except the results are placed directly in the ListBox or ComboBox specified by the hWnd and WindowType parameters. SearchData is placed in the ItemData field. The data will not be sorted unless the ListBox/ComboBox has a sorted style. GetMembersWithSubStringDirect returns the number of items which were added to the window.


GetMembersWithSubStringEx Method

Applies To

Function GetMembersWithSubStringEx(
  ByVal SubString As String,
  InvokeGroupings() As InvokeKinds,
  Optional StartResults As SearchResults,
  Optional ByVal SearchType As TliSearchTypes = tliStDefault,
  Optional ByVal SearchMiddle As Boolean = True,
  Optional ByVal Sort As Boolean = True,
  Optional ByVal ShowUnderscore As Boolean = False) As SearchResults

The GetMembersWithSubStringEx method of the TypeLibInfo object is used to retrieve a SearchResults collection with members that contain a given SubString. If SubString is an empty string or vbNullString, this method retrieves all member names. No duplicate names are retrieved. If SearchMiddle is True, then returned collection items will have SubString somewhere in the name of a member. Otherwise, SubString will be found only at the beginning of member names. All searches are case-insensitive.

Since member names are useless information without the ability also display the types to which the member belongs, the GetTypesWithMemberEx method is provided as a companion to GetMembersWithSubStringEx.

The SearchType and Sort and SearchResults parameters are used as described in the GetTypes method. See Hidden Property for information on the ShowUnderscore parameter.

The InvokeGroupings parameter groups members by InvokeKind. Since the same name can be used for both method and event in one library, and a property in another, simply getting a member name is insufficient to identify an object. For example, the rdoEnvironment object in the msrdo20.dll type library has both a BeginTrans method and a BeginTrans event. If InvokeGroupings is passed an empty SubString and an empty InvokeGroupings array (equivalent to using the obsoleted GetMembersWithSubString method), then the returned collection will contain only one BeginTrans SearchItem object, although you'd really like to see one BeginTrans collection item with an InvokeKinds property of INVOKE_FUNC, and a second with InvokeKinds equal to INVOKE_EVENTFUNC.

By setting the InvokeGroupings array to include different values from the InvokeKinds enum, you tell GetMembersWithSubStringEx to add an item to the collection if it doesn't already match not only a name in the collection, but also the InvokeGroup specified by the InvokeGroupings array. If InvokeGroupings is a non-empty array, then any item not matching a specified InvokeGroup is not placed in the collection. By default, the Sort method sorts first by InvokeGroup for SearchResults collections generated by GetMembersWithSubStringEx.

Typical InvokeGroupings

Constants, methods, properties, events (INVOKE_CONST must be before INVOKE_PROPERTY*)
INVOKE_CONST
INVOKE_FUNC
INVOKE_PROPERTYGET Or INVOKE_PROPERTYPUT Or INVOKE_PROPERTYPUTREF
INVOKE_EVENTFUNC

Methods, properties, events (constants are considered properties)
INVOKE_FUNC
INVOKE_PROPERTYGET Or INVOKE_PROPERTYPUT Or INVOKE_PROPERTYPUTREF
INVOKE_EVENTFUNC

Properties only
INVOKE_PROPERTYGET Or INVOKE_PROPERTYPUT Or INVOKE_PROPERTYPUTREF

Methods and Events only
INVOKE_FUNC
INVOKE_EVENTFUNC

Properties with different entries for GET/PUT/PUTREF
INVOKE_PROPERTYGET
INVOKE_PROPERTYPUT
INVOKE_PROPERTYPUTREF

Example: Use GetTypesWithMemberEx to examine BeginTrans members in RDO

Dim Groups(1) As InvokeKinds
Dim GroupNames(1) As String
Dim SIMember As SearchItem
Dim SIType As SearchItem
Groups(0) = INVOKE_FUNC Or INVOKE_PROPERTYGET Or _
            INVOKE_PROPERTYPUT Or INVOKE_PROPERTYPUTREF
GroupNames(0) = "Method or Property"
Groups(1) = INVOKE_EVENTFUNC
GroupNames(1) = "Event"
With TypeLibInfoFromFile("msrdo20.dll")
  .SearchDefault = tliStClasses Or tliStEvents
  For Each SIMember In .GetMembersWithSubStringEx("BeginTrans", Groups)
    Debug.Print "Types with " & SIMember & " ";
    Debug.Print GroupNames(SIMember.InvokeGroup – 1)
    For Each SIType In .GetTypesWithMemberEx(SIMember, SIMember.InvokeKinds)
      Debug.Print "  "; SIType
    Next
  Next
End With

Output:
Types with BeginTrans Method or Property
  rdoConnection
  rdoEnvironment
Types with BeginTrans Event
  rdoEnvironment


GetTypeInfo Property

Applies To

GetTypeInfo(ByVal Index As Variant) As TypeInfo

Use to retrieve a TypeInfo directly from a TypeLibInfo object. The Index parameter can specify either the Name or the TypeInfoNumber of the TypeInfo object. GetTypeInfo can be used as an alternative to retrieving a TypeInfo object using NamedItem or IndexedItem on the TypeInfos collection.


GetTypeInfoNumber Property

Applies To

GetTypeInfoNumber(ByVal Name As String) As Integer

Used to retrieve the TypeInfoNumber for a TypeInfo directly from a TypeLibInfo object. GetTypeInfoNumber is a fast alternative to calling NamedItem on the TypeInfos collection and then calling the TypeInfoNumber property.


GetTypeKind Property

Applies To

GetTypeKind(ByVal TypeInfoNumber As Integer) As TypeKinds

Used to retrieve the TypeKind of a TypeInfo directly from a TypeLibInfo object. GetTypeKind is a fast alternative to calling IndexedItem on the TypeInfos collection and then calling the TypeKind property.


GetTypes[Direct] Method

Applies To

Function GetTypes(
  Optional StartResults As SearchResults,
  Optional ByVal SearchType As TliSearchTypes = tliStDefault,
  Optional ByVal Sort As Boolean = True) As SearchResults
Function GetTypesDirect(
  ByVal hWnd As Long,
  Optional ByVal WindowType As TliWindowTypes = tliWtListBox,
  Optional ByVal SearchType As TliSearchTypes = tliStDefault) As Integer

The GetTypes method is used to retrieve a SearchResults collection containing the names and selected data of TypeInfo objects in a TypeLibInfo object. The set of types which are actually returned is determined by the SearchType parameter. GetTypes automatically determines relationships between types, eliminating the need for you to process the raw TypeInfos collection directly to get the subset of TypeInfos which are generally representative of the library. The returned types can also be affected by the current SearchCriteria setting.

To place types from more than one TypeLibInfo object in a SearchResults collection, set the StartResults parameter as the SearchResults object returned by the previous GetTypes call. You can distinguish between different libraries by setting the LibNum property before calling GetTypes. If you're placing results from multiple GetTypes calls in a single collection, set the Sort parameter to false and call the Sort method after the last library has contributed its data.

The GetTypesDirect method generates the same data as GetTypes, except the results are placed directly in the ListBox or ComboBox specified by the hWnd and WindowType parameters. SearchData is placed in the ItemData field. The data will not be sorted unless the ListBox/ComboBox has a sorted style. GetTypesDirect returns the number of items which were added to the window. See SearchData for an example which uses GetTypesDirect.

Example: Dump all of the TLI constants and values

Dim SIType As SearchItem
Dim SIMember As SearchItem
With TypeLibInfoFromFile("tlbinf32.dll")
  .SearchDefault = tliStConstants
  For Each SIType In .GetTypes
    For Each SIMember In .GetMembers(SIType.SearchData)
      Debug.Print SIMember, _
        .GetMemberInfo(SIType.SearchData, SIMember.InvokeKinds, SIMember.MemberId).Value
    Next
  Next
End With


GetTypesWithMember[Direct] Method

Applies To

Function GetTypesWithMember(
  ByVal MemberName As String,
  Optional StartResults As SearchResults,
  Optional ByVal SearchType As TliSearchTypes = tliStDefault,
  Optional ByVal Sort As Boolean = True,
  Optional ByVal ShowUnderscore As Boolean = False) As SearchResults
Function GetTypesWithMemberDirect(
  ByVal MemberName As String,
  ByVal hWnd As Long,
  Optional ByVal WindowType As TliWindowTypes = tliWtListBox,
  Optional ByVal SearchType As TliSearchTypes = tliStDefault,
  Optional ByVal ShowUnderscore As Boolean = False) As Integer

The GetTypesWithMember method is equivalent to the GetTypesWithMemberEx method called with an InvokeKind of INVOKE_UNKNOWN. GetTypesWithMember complements the GetMembersWithSubString method.

The GetTypesWithMemberDirect method generates the same data as GetTypesWithMember, except the results are placed directly in the ListBox or ComboBox specified by the hWnd and WindowType parameters. SearchData is placed in the ItemData field. The data will not be sorted unless the ListBox/ComboBox has a sorted style. GetTypesWithMemberDirect returns the number of items which were added to the window. See SearchData for an example which uses GetTypesDirect.


GetTypesWithMemberEx Method

Applies To

Function GetTypesWithMemberEx(
  ByVal MemberName As String,
  ByVal InvokeKind As InvokeKinds,
  Optional StartResults As SearchResults,
  Optional ByVal SearchType As TliSearchTypes = tliStDefault,
  Optional ByVal Sort As Boolean = True,
  Optional ByVal ShowUnderscore As Boolean = False) As SearchResults

The GetTypesWithMemberEx method of the TypeLibInfo object is used to retrieve a SearchResults collection with all types which have a member of the given MemberName and InvokeKind. If InvokeKind is INVOKE_UNKNOWN (0), then GetTypesWithMemberEx is equivalent to the GetTypesWithMember method. GetTypesWithMemberEx complements the GetMembersWithSubStringEx method, which generates a SearchResults collection of unique MemberName/InvokeKind pairs in a given library. If the same parameter settings are used, then calling GetTypesWithMemberEx with the Name/InvokeKind of a SearchItem object from a GetMembersWithSubStringEx collection will always produce a non-empty collection.

The SearchType and Sort and StartResults parameters are used as described in the GetTypes method. See Hidden Property for information on the ShowUnderscore parameter.

If a member occurs on a base class (or, even worse, on a base class in an external type library), then the GetTypesWithMemberEx collection will contain the base and all types which derive from the base. Similarly, if a member binds to a type which is aliased, the alias also appears in the GetTypesWithMemberEx collection. Of course, as with the GetTypes method, types don't appear if they don't match the SearchType or are filtered out by the current SearchCriteria.

Example: Retrieve types with members containing the string "Number"

Dim Groups(0) As InvokeKinds
Dim SIMember As SearchItem
Dim SIType As SearchItem
Groups(0) = INVOKE_PROPERTYGET
With TLI.TypeLibInfoFromFile("tlbinf32.dll")
  For Each SIMember In .GetMembersWithSubStringEx("Number", Groups)
    Debug.Print "**Types with " & SIMember & " Property**"
    For Each SIType In .GetTypesWithMemberEx(SIMember, SIMember.InvokeKinds)
      Debug.Print SIType
    Next
  Next
End With

Output:
**Types with GetTypeInfoNumber Property**
TypeLibInfo
**Types with TypeInfoNumber Property**
CoClassInfo
ConstantInfo
DeclarationInfo
InterfaceInfo
IntrinsicAliasInfo
RecordInfo
SearchItem
TypeInfo
UnionInfo
VarTypeInfo


GetTypesWithSubString[Direct] Method

Applies To

Function GetTypesWithSubString(
  ByVal SubString As String,
  Optional StartResults As SearchResults,
  Optional ByVal SearchType As TliSearchTypes = tliStDefault,
  Optional ByVal SearchMiddle As Boolean = True,
  Optional ByVal Sort As Boolean = True) As SearchResults
Function GetTypesWithSubStringDirect(
  ByVal SubString As String,
  ByVal hWnd As Long,
  Optional ByVal WindowType As TliWindowTypes = tliWtListBox,
  Optional ByVal SearchType As TliSearchTypes = tliStDefault,
  Optional ByVal SearchMiddle As Boolean = True) As Integer

The GetTypesWithSubString method of the TypeLibInfo object is used to retrieve a SearchResults collection with types that contain a given SubString. If SubString is an empty string or vbNullString, this method is equivalent to GetTypes. If SearchMiddle is True, then returned collection items will have SubString somewhere in the name of a type. Otherwise, SubString will be found only at the beginning of item names. All searches are case-insensitive. Parameters other than SubString and SearchMiddle are the same as the corresponding parameters in the GetTypes method, and GetTypesWithSubStringDirect is analogous to GetTypesDirect.

Example: Searching TLI for types containing and beginning with 'co'

Dim SI As SearchItem
With TypeLibInfoFromFile("tlbinf32.dll")
  Debug.Print "**Types Containing 'co'**"
  For Each SI In .GetTypesWithSubString("co")
    Debug.Print SI
  Next
  Debug.Print "**Types Beginning With 'co'**"
  For Each SI In .GetTypesWithSubString("co", , , False)
    Debug.Print SI
  Next
End With

Output:
**Types Containing 'co'**
CallConvs
CoClasses
CoClassInfo
ConstantInfo
Constants
CustomDataCollection
RecordInfo
Records
**Types Beginning With 'co'**
CoClasses
CoClassInfo
ConstantInfo
Constants


GUID Property

Applies To

GUID As String

The GUID is the string, or registry format, form of the GUID (globally unique identifier) of a TypeLibInfo or TypeInfo object. When a type library is properly registered, some of its GUID's are placed in the system registry. These entries are known as LIBID's (the GUID property of a TypeLibInfo) object, CLSID's (the GUID property of a CoClassInfo) object, and IID's (the GUID property of an InterfaceInfo) object.


Help* Properties

Applies To

HelpString(Optional LCID As Long) As String
HelpStringDll(Optional LCID As Long) As String
HelpStringContext As Long
HelpFile As String
HelpContext As Long

Type libraries can contain help information for the library itself (TypeLibInfo object), each TypeInfo (TypeInfo object), and each member (MemberInfo object). This information is available in several different forms.

HelpString is the documentation string which appears as a short description of the string in object browsers. If the optional LCID (Language/Country identifier) is specified, then the returned string is localized if possible.

Documentation strings can be stored either in the type library directly or retrieved via a call to the DLLGetDocumentation entry point in the Dll specified by the HelpStringDll property. The HelpStringContext is passed to the HelpStringDll to get the correct documentation string for the object. The HelpStringDll and HelpStringContext properties values are used automatically by the HelpString property, so there is generally no need to call these directly. However, they're included for completeness and to facilitate IDL/ODL regeneration.

The HelpFile and HelpContext properties specify the help topics for the given item. Use these properties to launch an associated help file for information beyond what is given by the HelpString property. Although available on all objects which support help, the HelpFile property is always the same throughout a type library, so getting it once from the TypeLibInfo is sufficient.


Hidden Property

Applies To

Hidden As Boolean

Indicates whether a SearchItem object is hidden. In order to get hidden items, you must explicitly modify the types filters with ResetSearchCriteria and/or the member filters. Hidden members are indicated either with AttributeMask settings on types or members, or by starting the member name with a leading underscore (_) character. Modifying filters will include types and members marked as hidden with a normal flag, but not those considered hidden because of a leading underscore. In order to always get hidden methods, pass True to all ShowUnderscore parameters on methods which return SearchResults collections.

Retrieving the Hidden property from SearchResults collection items returned from methods which are not in the Applies To list will raise error tliErrNotApplicable.


Interfaces, ImpliedInterfaces Properties

Applies To

Interfaces As Interfaces
ImpliedInterfaces As Interfaces

The Interfaces property applies to TKIND_COCLASS type TypeInfo objects and returns the collection of interfaces in the coclass. InterfaceInfo objects obtained from this collection return different AttributeMask values, but all other properties return the same information as if they had been retrieved directly from the TypeInfos collection. The NamedItem and IndexedItem accessor functions have no meaning with this type of Interfaces collection and will return a standard Subscript out of range error (0x800A0009).

The ImpliedInterfaces property applies to an InterfaceInfo (TKIND_INTERFACE or TKIND_DISPATCH type) TypeInfo object. This collection always has a Count of either 0 or 1. If the Count is 1, then the InterfaceInfo has a base class. For a TKIND_DISPATCH object, this base will always be IDispatch. However, for TKIND_INTERFACE, you must walk the bases to get all members of the interface. (See VTableInterface for more information). If you use the GetMembers method, then all base class resolution is done automatically.

Note that ImpliedInterfaces applies only to objects declared as InterfaceInfo. If the same object is referenced by a variable of type TypeInfo, then use the Interfaces property to return the ImpliedInterfaces collection.


TypeInfos Collection Accessor Properties

Applies To

Item(ByVal Index As Integer) As TypeInfo
IndexedItem(ByVal TypeInfoNumber As Integer) As TypeInfo
NamedItem(ByVal TypeInfoName As String) As TypeInfo

Individual TypeInfo items in the TypeInfos collection can be retrieved using three different accessor properties, or using For Each on the collection.

Item (the default property) is an index directly into the current collection. TLI collections are 1-based, so the valid range for the Index parameter is 1 to TypeInfos. Count.

Use IndexedItem to retrieve a TypeInfo by its TypeInfoNumber in the type library. Type libraries are 0 base, so the valid range for the TypeInfoNumber parameter is 0 to TypeLibInfo.TypeInfoCount.

If you know the name of a TypeInfo, but not its TypeInfoNumber, then use the NamedItem accessor property. NamedItem should be used only if the TypeInfoNumber isn't readily available since it is a much slower lookup. Any valid TypeInfo name from the type library can be used.

Note that for performance reasons, IndexedItem and NamedItem do no validation to ensure that the returned TypeInfo object actually belongs to the subset collection. Therefore, CoClasses.NamedItem can actually return an InterfaceInfo. Since the TypeInfos collection is cheaper than the subset collections to generate, IndexedItem and NamedItem are generally used only with the TypeInfos collection.


InvokeGroup Property

Applies To

InvokeGroup As Integer

For a SearchItem object resulting from a call to GetMembersWithSubStringEx, the InvokeGroup property corresponds to the matched grouping in the array passed to the InvokeGroupings parameter. InvokeGroup is 1-based, regardless of the base of the passed in array.

Retrieving the InvokeGroup property from SearchResults collection items returned from methods which are not in the Applies To list will raise error tliErrNotApplicable.


Invoke* Methods and Properties

Applies To

Function InvokeHook (ByVal Object As Object, ByVal NameOrID As Variant,
    ByVal InvokeKind As InvokeKinds, ParamArray ReverseArgList() As Variant) As Variant
Function InvokeHookArray(ByVal Object As Object, ByVal NameOrID As Variant,
    ByVal InvokeKind As InvokeKinds, ReverseArgList() As Variant) As Variant
Sub InvokeHookSub(ByVal Object As Object, ByVal NameOrID As Variant,
    ByVal InvokeKind As InvokeKinds, ParamArray ReverseArgList() As Variant)
Sub InvokeHookArraySub(ByVal Object As Object, ByVal NameOrID As Variant,
    ByVal InvokeKind As InvokeKinds, ReverseArgList() As Variant)
Function InvokeID(ByVal Object As Object, ByVal Name As String) As Long
InvokeLCID As Long

The Invoke members of the TLIApplication object allow you to easily use IDispatch::Invoke directly from VB code. This means that you can call a property or method on an object without knowing the name of the property or method at compile time. Although VB6 introduced the CallByName function, which has similar functionality, the TLI Invoke functionality offers you much more flexibility.

There are 4 different InvokeHook* functions in TLI. All 4 functions have similar parameters.

  • Object is the object which you want to manipulate.

  • NameOrID is the name of the property or method to call, or the MemberId corresponding to that name. If you pass in a name, then InvokeHook must call GetIDsOfNames to resolve the name into a MemberId, then Invoke to make the actual call. For objects running in a different process or on a different machine, this is an extra context switch and means that InvokeHook is approximately twice as slow as when it receives a MemberId directly. Therefore, if you're calling a function multiple times, you should first resolve the ID. This can be done using object inspection if the object supports it, or by first calling the TLI.InvokeID function with the Object and Name. InvokeID calls GetIDsOfNames directly to look up the name instead of using retrieving a TypeInfo from the running object.

  • InvokeKind specifies the type of call being made. If you're making a call which assigns a property value (obj.prop = val), use INVOKE_PROPERTYPUT. For assigning an object reference to a property (Set obj.prop = ref), use INVOKE_PROPERTYPUTREF. For retrieving a property value (val = obj.prop), use INVOKE_PROPERTYGET, and INVOKE_FUNC for a function call. Since calling a Function and a Property Get are syntactically equivalent, if you're not sure which one you're calling, specify both (INVOKE_FUNC Or INVOKE_PROPERTYGET).

  • ReverseArgList is a list of parameters in reverse order, which is how IDispatch::Invoke wants them. For INVOKE_PROPERTYPUT[REF], the first parameter passed is the right-hand side value. If you use InvokeHook, then ReverseArgList is a ParamArray and the parameters are passed in one at a time. This is easy to code, and VBA automatically supports ByRef parameters when you use a ParamArray. However, if you need to determine the number of parameters at runtime, then you can't use a ParamArray. In this case, use InvokeHookArray, which takes an array of Variants for a ReverseArgList, allowing you to dynamically modify the number of parameters you're passing.

The InvokeHookSub and InvokeHookArraySub are the same as InvokeHook[Array] except that they don't support a return value. The standard IDispatch implementation simply returns an empty Variant if the called function doesn't have a return value. However, some IDispatch implementations (in particular, VB intrinsic controls) will raise an error in this case. The InvokeHook[Array]Sub functions are provided to explicitly call Invoke without a request for a return value.

IDispatch::Invoke takes an LCID (language/country identifier) parameter. TLI defaults this value to LANG_USER_DEFAULT (&H400), but allows you to set it via the TLI.InvokeLCID property. Since this value is confusing to most users, rarely used, and generally has no variation between InvokeHook calls, InvokeLCID was made a separate property instead of a parameter to InvokeHook*.

Any errors, including rich error information, which are raised by the IDispatch::Invoke call are propagated forward and appear as errors on the InvokeHook* functions.

If you use InvokeHookArray and fill the ReverseArgList array with normal VB code, then the parameters are passed ByVal. In order to support ByRef parameters with InvokeHookArray, you'll have to modify the Variants in the argument list by assigning a Long pointer value to the Variant, then using the CopyMemory API to modify the vt (VarType) field in the underlying Variant structure to be the VarType of the argument combined with the VT_BYREF bit.

Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
  (pDst As Any, pSrc As Any, ByVal ByteLen As Long)
Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" _
  (Ptr() As Any) As Long
'Note: VarPtrArray works for all types except String arrays.  For string arrays,
'you need the following declare in module section of a referenced type library.
'    [entry("VarPtr")]
'    long _stdcall VarPtrStringArray([in] SAFEARRAY (BSTR) *Ptr);
Dim obj As Object
Dim args() As Variant
Dim i As Integer
Dim iArr() As Integer
Dim vt As Integer
Dim InvokeID As Long
  'Call Foo(i As Integer, iArr() As Integer)
  ReDim args(1)
  'Use this code only with variable sized arrays.
  args(0) = VarPtrArray(iArr)
  vt = VT_BYREF Or VT_ARRAY Or VT_I2
  CopyMemory args(0), vt, 2
  args(1) = VarPtr(i)
  vt = VT_BYREF Or VT_I2
  CopyMemory args(1), vt, 2
  TLI.InvokeHookArray obj, "Foo", INVOKE_FUNC, args

If you have optional parameters which you don't want to pass, then you simply omit them if they occur at the end of the parameter list, which is actually the beginning of the list from an InvokeHook perspective. If you want to skip an optional parameter with InvokeHookArray while specifying parameters which come after it, then you need to supply the special Variant Missing value, regardless of whether the optional parameter is typed as Variant or some other type. The Missing value can be obtained by calling the GetMissing function shown here without specifying a parameter.

Function GetMissing(Optional ByVal DontPass As Variant) As Variant
  GetMissing = DontPass
End Function


InvokeKind, InvokeKinds Properties, InvokeKinds Enum

InvokeKind, InvokeKinds Properties; InvokeKinds Enum

Applies To

'MemberInfo object
InvokeKind As InvokeKinds
'SearchItem object
InvokeKinds As InvokeKinds

Enum InvokeKinds
  INVOKE_UNKNOWN = 0,
  INVOKE_FUNC = 1,
  INVOKE_PROPERTYGET = 2,
  INVOKE_PROPERTYPUT = 4,
  INVOKE_PROPERTYPUTREF = 8,
  'Special TLI values
  INVOKE_EVENTFUNC = 16,
  INVOKE_CONST = 32
End Enum

The InvokeKind property of a MemberInfo object indicates how a member function can be called from code. If a function can be called more than one way, then the Members collection has separate entries for each syntax that the function supports. If a MemberInfo has a DescKind of DESCKIND_VARDESC or was retrieved using the GetMember of GetMemberInfo methods, then the InvokeKind property returns INVOKE_UNKNOWN. The combination of Name or MemberId and InvokeKind uniquely determines a MemberInfo object in the Members collection. The following table shows the four standard InvokeKinds and the corresponding function definitions and calls in VB.

InvokeKind | VB Equivalent | How to call from VB
INVOKE_FUNC | Sub or Function | func param1, param2, ... or retval = func(param1, param2, ...)
INVOKE_PROPERTYGET | Property Get | value = obj.prop(...)
INVOKE_PROPERTYPUT | Property Put | obj.prop(...) = value
INVOKE_PROPERTYPUTREF | Property Set | Set obj.prop(...) = object reference

The FUNC and PROPERTY* InvokeKind values correspond to INVOKEKIND as defined in the OLE Automation headers. The values INVOKE_EVENTFUNC and INVOKE_CONST are returned by the InvokeKinds property of a SearchItem object and are relevant only to TLI.

Unlike the InvokeKind property, the InvokeKinds property of the SearchItem object can return multiple INVOKE_* values (hence the plurality of the property name). One of the main advantages of using the GetMembers* methods, in fact, is that you actually get information about multiple MemberInfo items in a single SearchItem object. For example, a read-write property will have two MemberInfo objects in the Members collection, but only 1 item (with a complex InvokeKinds property) in the corresponding SearchResults collection returned by the GetFilteredMembers method.

When InvokeKinds returns INVOKE_EVENTFUNC, it means that the member is actually an event of the object, not a member. Since events are actually described in a type library as functions, they always have a natural InvokeKind of INVOKE_FUNC, which makes then indistinguishable from methods when properties, methods, and events are included in the same collection. See SearchType for more information on including events in SearchResults collections.

INVOKE_CONST indicates that an item corresponds to a constant value. When this bit is set, INVOKE_PROPERTYGET and INVOKE_PROPERTYPUT may also be set, so check INVOKE_CONST first, and list it before any PROPERTY flags in the InvokeGroupings parameter of the GetMembersWithSubStringEx method.

If a member has a DescKind of DESCKIND_VARDESC, then the natural InvokeKind isn't specified. However, for grouping and general information purposes, it is beneficial if the GetMembers* methods determine a matching InvokeKind for each variable. This is done by checking the VARFLAG values for the member. If VARFLAG_FREADONLY is set, then the item is considered a PROPERTYGET only. If this isn't set, then the type of the variable must be checked to determine if the item should be considered a PROPERTYPUT or a PROPERTYPUTREF. For performance reasons, the type check is skipped for the GetMembersWithSubStringEx method and all 3 property bits are set in the InvokeKinds field. Since the constant check check is made independently, and constants don't always have the VARFLAG_FREADONLY bit set, you can get the anomaly that a constant member also has INVOKE_PROPERTYPUT bit set.

Example: Map InvokeKinds to the correspond VB function type

Function InvokeInfo(ByVal InvKinds As TLI.InvokeKinds) As String
  If InvKinds And INVOKE_CONST Then
    InvokeInfo = "Constant"
    Exit Function
  End If
  Select Case InvKinds
    Case INVOKE_EVENTFUNC
      InvokeInfo = "Event"
    Case INVOKE_FUNC
      InvokeInfo = "Method"
    Case INVOKE_PROPERTYGET
      InvokeInfo = "Property Get"
    Case INVOKE_PROPERTYPUT
      InvokeInfo = "Property Let"
    Case INVOKE_PROPERTYPUTREF
      InvokeInfo = "Property Set"
    Case INVOKE_PROPERTYPUT Or INVOKE_PROPERTYGET
      InvokeInfo = "Property Get/Let"
    Case INVOKE_PROPERTYPUTREF Or INVOKE_PROPERTYGET
      InvokeInfo = "Property Get/Set"
    Case INVOKE_PROPERTYPUTREF Or INVOKE_PROPERTYPUT
      InvokeInfo = "Property Let/Set"
    Case INVOKE_PROPERTYGET Or INVOKE_PROPERTYPUTREF Or INVOKE_PROPERTYPUT
      InvokeInfo = "Property Get/Let/Set"
  End Select
End Function


IsExternalType, TypeLibInfoExternal Properties

Applies To

IsExternalType As Boolean
TypeLibInfoExternal As TypeLibInfo

If the TypeInfo object represented by a VarTypeInfo object is defined in a different type library than the one which defines the MemberInfo object used to retrieve the VarTypeInfo object, then this property is True. If IsExternalType is True, then the TypeLibInfoExternal property returns a TypeLibInfo object which represents the external library. For an external library, the TypeLibInfoExternal is equivalent to .TypeInfo.Parent. If an external library isn't registered on the current system, then these properties will raise an error.

Example: Check for external library

Dim TLIVB6 As TypeLibInfo
Set TLIVB6 = TypeLibInfoFromFile("c:\vb6\vb6.olb")
With TLIVB6.CoClasses.NamedItem("PictureBox"). _
     DefaultInterface.GetMember("Picture").ReturnType
    Debug.Print .IsExternalType, _
                .TypeLibInfoExternal Is Nothing, _
                TLIVB6.IsSameLibrary(.TypeInfo.Parent)
End With

Output:
True    False    False


IsSameLibrary Method

Applies To

IsSameLibrary(ByVal CheckLib As TypeLibInfo) As Boolean

Use to see if a second TypeLibInfo object refers to the same type library as this one. IsSameLibrary is equivalent to using the VBA Is operator on the ITypeLib property of two TypeLibInfo objects.


ITypeInfo Property, TypeInfoFromITypeInfo Method

Applies To

ITypeInfo As IUnknown
TypeInfoFromITypeInfo(ByVal ptinfo As IUnknown) As TypeInfo

Inside every TypeInfo is a reference to an ITypeInfo instance. In fact, the TypeInfo object can be viewed as a wrapper on the ITypeInfo interface which is easier to program against ITypeInfo itself. To see if two TypeInfo objects actually refer to the same internal object, use VB's Is operator with the ITypeInfo property of the two objects. The Is operator will usually return False for TypeInfo objects which actually correspond to the same underlying type, but not for the internal ITypeInfo pointers. The ITypeInfo property is read-only.

If you have an ITypeInfo reference and want to use TLI objects, then you can call TLI.TypeInfoFromITypeInfo to generate a fully functional TypeInfo object directly from your ITypeInfo reference.

The ITypeInfo property and TypeInfoFromITypeInfo method are considered advanced features and are marked as hidden.


ITypeLib Property, TypeLibInfoFromITypeLib Method

Applies To

ITypeLib As IUnknown
TypeLibInfoFromITypeLib (ByVal ptlib As IUnknown) As TypeLibInfo

Inside every TypeLibInfo is a reference to an ITypeLib instance. In fact, the TypeLibInfo object can be viewed as a wrapper on the ITypeLib interface which is easier to program against than ITypeLib itself. To see if two TypeLibInfo objects actually refer to the same internal object, use VB's Is operator with the ITypeLib property of the two objects. The Is operator will usually return False for TypeLibInfo objects which actually correspond to the same underlying type, but not for the internal ITypeLib pointers. The ITypeLib property is settable, so you can put a TypeLibInfo object on top of an existing ITypeLib.

If you have an ITypeLib reference and want to use TLI objects, then you can call TLI.TypeLibInfoFromITypeLib to generate a fully functional TypeLibInfo object.

The ITypeLib property and TypeLibInfoFromITypeLib method are considered advanced features and are marked as hidden.


LCID Property

Applies To

LCID As Long

The LCID (language/country identifier) property of a TypeLibInfo object indicates the language under which the type library is to be registered. This property, along with the GUID, MajorVersion, and MinorVersion; uniquely define a registered type library on a system. To load a type library based on the registry, see the LoadRegTypeLib and TypeLibInfoFromRegistry methods.


LibNum, ShowLibName Properties

Applies To

LibNum As Integer
ShowLibName As Boolean

In order to generate a SearchResults collection which spans data from multiple TypeLibInfo objects, TLI lets you assign a library number to a TypeLibInfo object. A LibNum of 0 indicates no data. Valid library numbers are 1-2047. This value is limited to enable encoding the LibNum in a SearchData Long value. If LibNum is set and you set ShowLibName to true, then any GetTypes* methods will place the library name after the type name, so the Name property of the SearchItem object will return Worksheet (Excel) instead of Worksheet. This allows you to show objects from multiple libraries in the same collection.

The LibNum is available directly from a SearchItem object. Since TLI doesn't provide a TypeLibs collection, you are responsible for mapping the LibNum back to the TypeLibInfo which generated it. See AddTypes for sample code which places TypeLibInfo objects in a VBA Collection. Retrieving the LibNum property from SearchResults collection items returned from methods which are not in the Applies To list will raise error tliErrNotApplicable.


LoadRegTypeLib Method, TypeLibInfoFromRegistry Method

Applies To See Also

LoadRegTypeLib(ByVal TypeLibGuid As String,
               ByVal MajorVersion As Integer,
               ByVal MinorVersion As Integer,
               ByVal LCID As Long)
TypeLibInfoFromRegistry(ByVal TypeLibGuid As String,
                        ByVal MajorVersion As Integer,
                        ByVal MinorVersion As Integer,
                        ByVal LCID As Long) As TypeLibInfo

The LoadRegTypeLib method of a TypeLibInfo object loads the type library uniquely specified by the passed in parameters in the system registry. The location of the type library to load is determined by the key HKEY_CLASSES_ROOT\TypeLib\TypeLibGuid\MajorVersion.MinorVersion\LCID\win32

TLI.TypeLibInfoFromRegistry is used to create a TypeLibInfo object directly from the registry settings and is equivalent to creating a New TypeLibInfo object and then calling the LoadRegTypeLib method.

The LoadRegTypeLib method can be called at any time to switch the type library being viewed by the TypeLibInfo instance. The LoadRegTypeLib method, and ContainingFile and ITypeLib properties—together with the corresponding globally accessible TLIApplication methods—are the only ways to load a type library into a TypeLibInfo object. If a valid type library isn't loaded, most other TypeLibInfo member functions will return tliErrNoCurrentTypelib.


Locate, LocateSorted Methods

Applies To

Locate(Optional ByVal SearchString As String,
  Optional ByVal CustomSort As CustomSort,
  Optional ByVal StartAfter As Long) As Long
LocateSorted(ByVal CustomSort As CustomSort) As Long

Used to rapidly locate the index of a SearchItem object in a SearchResults collection. You must provide a value for at least one of the SearchString and CustomSort parameters. Locate works by visiting each item in the collection until it finds a match, then returning the Index of the item in the collection. If you specify the SearchString parameter, then Locate will first check the string against you're item. If there is a match, then it will verify the match with the passed in CustomSort interface, or just return the matching index if CustomSort isn't provided.

The Compare method of the CustomSort interface will be called with the matching object in the Item1 parameter and the Item2 parameter set to Nothing. You're implementation of the Compare callback function must have enough information to determine if the passed in item is the match you're looking for.

Locate works differently on Sorted and unsorted SearchResults collections. For an unsorted collection, Locate does a linear search (unless the collection comes from GetMembersWithSubStringEx, in which case the data is rapidly accessible via a hash table). In the non-sorted case, you must specify the SearchString parameter or Locate with raise a tliErrSearchResultsNotSorted error. For an unsorted collection, the sign of a non-zero return in the Compare parameter of the CustomSort_Compare function is ignored. A zero returns indicates a match, and a non-zero return indicates that Locate should continue.

For a sorted collection, Locate performs a fast binary search on the sorted data. If you've applied the Sort method with a custom sort which doesn't respect the normal string sort order, then don't specify the SearchString parameter. Calling Locate on a sorted collection with no SearchString is equivalent to calling the hidden LocateSorted method, which is included for compatibility with earlier TLI versions.

To start searching a collection at something other than the first item, set the StartAfter parameter to something other than 0. For an unsorted collection, StartAfter provides an alternative mechanism to using CustomSort for finding a specific item. Simply Locate, retrieve and check the SearchItem object at the returned Index, then call Locate again using the previous return as the new StartAfter value. Because of the binary search, this technique isn't reliable on a sorted collection.


MajorVersion, MinorVersion Properties

Applies To

MajorVersion As Integer
MinorVersion As Integer

The MajorVersion and MinorVersion of a TypeLibInfo are used for versioning of the type library in the registry and by compilers. These two properties, along with GUID and LCID, uniquely define a registered type library on a system. To load a type library based on the registry, see the LoadRegTypeLib and TypeLibInfoFromRegistry methods.

For a TypeInfo, the version is generally ignored by compilers. These properties are included in TLI for completeness.


SearchData Property, MakeSearchData Method

Applies To

'SearchItem object
SearchData As Long
'TypeLibInfo object
MakeSearchData(
  ByVal TypeInfoName As String,
  Optional ByVal SearchType As TliSearchTypes = TliStDefault) As Long

SearchData is the key that binds SearchResults collection which hold information about types to SearchResults collections containing member information. SearchData is available on every SearchResults collection item returned by the methods in the Applies To list. SearchData is also the first parameter in the GetMembers and GetMemberInfo methods, identifying the type for which the member data is needed.

If you need a SearchData value but haven't generated a SearchResults collection, you can use the MakeSearchData method to generate one for you. Simply pass the name of a TypeInfo and the desired SearchType to MakeSearchData. MakeSearchData will return a Subscript out of range error (&H800A0009) if the name isn't recognized, and a tliErrIncompatibleSearchType if the requested SearchType or current filters settings are such that the type wouldn't be returned by the GetTypes method. If you don't know the SearchType you need, then pass in tliStAll and MakeSearchData will figure it out. MakeSearchData is also the only method where you can pass in a tliStAppObject SearchType.

Example: Retrieving a MemberInfo object with MakeSearchData

Dim MI As MemberInfo
Dim TLInf As TypeLibInfo
Set TLInf = TLI.TypeLibInfoFromFile("tlbinf32.dll")
Set MI = TLInf.GetMemberInfo(TLInf.MakeSearchData("TypeLibInfo"), , , "MakeSearchData")

A SearchData value is actually a packed long which contains the SearchType, LibNum, TypeInfoNumber data for a SearchItem object. A flag specifying if the item is Hidden is also packed into the SearchData for convenience. All of this data is packed into a Long value to accomodate storing this identifying data in the ItemData field of a ListBox or ComboBox control. For the *Direct methods, the SearchData is automatically placed in the ItemData field, as shown in the following example.

Example: Building a minimal object browser in VB

'Given a VB form with two ListBox controls, a TextBox, a Label,
'and a Command Button, load a type library based on Text1,
'show types in List1 and members in List2.  The PrototypeMember
'function is defined in the linked topic.
Option Explicit
Private m_TLInf As TypeLibInfo
Private Sub Form_Load()
  Set m_TLInf = New TypeLibInfo
  m_TLInf.AppObjString = "<Unqualified>"
End Sub
Private Sub Command1_Click()
  On Error Resume Next
  m_TLInf.ContainingFile = Text1
  If Err Then Beep: Exit Sub
  List2.Clear
  With List1
    .Clear
    m_TLInf.GetTypesDirect .hWnd
    If .ListCount Then .ListIndex = 0
  End With
End Sub
Private Sub List1_Click()
  With List1
    List2.Clear
    'Retrieve the SearchData from the ItemData property
    TLInf.GetMembersDirect .ItemData(.ListIndex), List2.hWnd
  End With
End Sub
Private Sub List2_Click()
Dim InvKinds As TLI.InvokeKinds
    With List2
        InvKinds = .ItemData(.ListIndex)
        Label1 = PrototypeMember(m_TLInf, _
                                 List1.ItemData(List1.ListIndex), _
                                 InvKinds, , .[_Default])
    End With
End Sub

Since each of the fields in a SearchData are also available in other properties on the SearchItem object, you should only have to dissect a SearchData value if you're using *Direct methods. Even then, you shouldn't need more than the LibNum. In previous TLI versions, SearchData was in a Byte|Byte|Integer (SearchType|LibNum|TypeInfoNumber) format. This has been adjusted by stealing bits from the TypeInfoNumber field to allow more libraries. However, if you don't use a LibNum greater than 255, and you don't modify filters to include the hidden bit, then the Byte|Byte|Word format is still valid. The limits of SearchData are 2047 libraries and libraries with a maximum TypeInfoCount of 4096. If there are more than 4096 TypeInfo objects, then the TypeInfoNumber property on the SearchItem object is bogus. In this case, you can pass the Name property to the GetTypeInfoNumber method to retrieve a valid TypeInfoNumber [I've never actually met a type library which didn't fit in the allotted space]. Below are C macros and VB routines to build and dissect a SearchData Long value, just in case you need them. See SearchData Expansion Functions for C and VB routines to expand or build a SearchData value.


Me Property

Every TLI object has a hidden Me property which returns a reference to the object. Me is included to let you access the object in the VB's With statement inside the With block.


MemberId Property

Applies To

MemberId As Long

The MemberId of a MemberInfo object is a numeric identifier which has a one-to-one mapping to the member Name. This mapping doesn't mean that a Name/MemberId pair is unique in a Members collection, since functions with different InvokeKind values can have the same Name/MemberId. The MemberId can be retrieved direction from SearchResults collection items returned by methods in the Applies To list. The MemberId value is used in calls to the GetMember, GetMemberInfo, and InvokeHook* methods. The terms MemberId and InvokeId are interchangeable.


Name Property

Applies To

Name As String

The name of a TypeLibInfo, TypeInfo, MemberInfo, ParameterInfo, or SearchItem object. Name is the default property for all of these objects. For a SearchItem object, see also NamePtrW.


NamePtrW Property

Applies To

NamePtrW As Long

A SearchResults collection stores a string for every item in the collection. A call to SearchItem.Name actually produces a copy of this string, which is an inefficient process. In order to eliminate string copies for time critical code, NamePtrW is provided as a hidden member for code optimization. The returned value is a BSTR pointer.


Parent Property

Applies To

Parent As TypeLibInfo

The Parent property is available on every TypeInfo type object and returns the TypeLibInfo object which represents the library in which the object is defined. If the TypeInfo is obtained directly from a running object via InterfaceInfoFromObject or ClassInfoFromObject (as opposed to being retrieved from a TypeLibInfo object), then the Parent property may return an error, depending on the implementation of the object.


PointerLevel Property

Applies To

PointerLevel As Integer

A numeric value indicating the number of levels of indirection required to reach the underlying type of VarTypeInfo object. Generally, this will be 0 (ByVal) or 1 (ByRef). However, if the VarType property indicates that the type represented is an array or TypeInfo and the TypeInfo has TypeKind TKIND_INTERFACE, TKIND_DISPATCH, or TKIND_COCLASS, then 1 is ByVal and 2 is ByRef. See also ElementPointerLevel.


RecordField Property, TypeInfoFromRecordVariant Method

Applies To

TypeInfoFromRecordVariant(RecordVariant As Variant) As TypeInfo
RecordField(RecordVariant As Variant, FieldName As String) As Variant

Starting with the release of VB6, VB and OLE Automation now support storing Records in Variants with the VT_RECORD variant type. As with object inspection, there is no built-in VB support to ask an arbitrary Record Variant which fields it supports, or to manipulate fields in an arbitrary Record Variant. TLI supports a simple mechanism for both inspecting and setting the fields of a Record Variant. To inspect the fields of a record, first obtain a TypeInfo with the TypeInfoFromRecordVariant method. You can now obtain field names from the Members collection of the TypeInfo object.

Once you've obtained field names and types, you can read or modify fields using the RecordField property. Unlike TLI's InvokeHook functionality, where the InvokeKind is explicitly passed as a parameter, the InvokeKind of the RecordField call is determined by the placement of the RecordField property itself.

Example: Using RecordField property

Type MyType
  Name As String
  Data As Object
End Type
Dim MT As MyType
Dim Var As Variant
Var = MT
'Equivalent statement pairs
Var.Name = "Curland"
RecordField(Var, "Name") = "Curland"
Debug.Print Var.Name
Debug.Print RecordField(Var, "Name")
Set Var.Data = DataObject
Set RecordField(Var, "Data") = DataObject


Register and UnRegister Methods

Register, UnRegister Methods

Applies To

TypeLibInfo.Register
TypeLibInfo.UnRegister

Register or UnRegister the type library represented by the TypeLibInfo object in the system registry. Registering a type library also adds keys to the Interface section for every TypeInfo with a TypeKind of TKIND_DISPATCH, as well as every TypeInfo with a TypeKind of TKIND_INTERFACE and the TYPEFLAG_FDUAL or TYPEFLAG_FOLEAUTOMATION (but not TYPEFLAG_FPROXY) flags set.

Registering a type library does not add any information to the CLSID key, which means that no new creatable objects are added to your system by registering a type library. In order to correctly register an ActiveX Dll or Ocx, you must call the DllRegisterServer entry point (use the regsvr32 utility, or browse using the VB References dialog to force registration). Exe (and Dll) components generally require you to run setup to fully support creating the object.

If you're using TLI objects from a safe scripting environment such as inside an Internet Browser, then the Register and UnRegister methods will raise an error.


ResolveAliases Property

Applies To

The global ResolveAliases property specifies whether VarTypeInfo objects represent the top level type, or the fully resolved type. For example, when ResolveAliases is True (the default), the VarTypeInfo object for a parameter typed as OLE_COLOR will have a VarType property of VT_UI4, which is the fundamental type of the OLE_COLOR alias. With TLI.ResolveAliases set to False, the VarType property will be VT_EMPTY and the TypeInfo property will hold a description of the OLE_COLOR type.

For compatibility with earlier TLI versions, this property defaults to True. Unfortunately, current standards generally require this property to be False, so be sure to set it before using VarTypeInfo objects. You can always find the underlying type for a TKIND_ALIAS TypeInfo by using the ResolvedType property.


ResolvedType Property

Applies To

ResolvedType As VarTypeInfo

If a TypeInfo object has a TypeKind of TKIND_ALIAS, then you can use the ResolvedType property to retrieve the VarTypeInfo object for the type being aliased. For aliases which are themselves aliases, you will have to call ResolvedType multiple times. ResolvedType will raise the tliErrIncompatibleTypeKind if the object is not an alias.

Note that TypeInfo object members which require a fully resolved type (GetMember, Members, and Interfaces) will automatically use the fully resolved type.

Example: Resolve a TKIND_ALIAS TypeInfo

Dim TIType As TypeInfo
Dim TIResolved As TypeInfo
Dim TKind As TypeKinds
  Set TIResolved = TIType
  TKind = TIResolved.TypeKind
  On Error Resume Next
  Do While TKind = TKIND_ALIAS
    TKind = TKIND_MAX
    Set TIResolved = TIResolved.ResolvedType
    If Err Then
      Err.Clear
    Else
      TKind = TIResolved.TypeKind
    End If
  Loop
  On Error GoTo 0
  If TKind = TKIND_MAX Then
    'Error occurred
  End If


SearchType, SearchDefault Properties, TliSearchTypes Enum

Applies To

'SearchItem object
SearchType As TliSearchTypes
'TypeLibInfo object
SearchDefault As TliSearchTypes

The SearchType parameter, which is applicable to all methods in the Applies To list, determines which subset of the various TypeInfos collections should be walked to determine the types and members returned in the generated SearchResults collections. A typical SearchType value is a combination of values from the TliSearchTypes enum. To avoid repeatedly passing the same SearchType value, use the SearchDefault property to specify the current setting, then pass in the tliStDefault (the default enum value) for the SearchType parameter. SearchDefault initializes to tliStAll. The following table describes each of the enum members.

Name

Description
tliStDefault | Use the current value of the SearchDefault property.
tliStClasses | Show the classes and interfaces which aren't eliminated by the current filters. If an interface is the default interface of a coclass, then return only the coclass (if it isn't filtered out). If an interface is an event interface in any coclass, then it is ignored. tliStClasses returns a subset of the items in the union of the CoClasses and Interfaces collections.
tliStEvents | Adjust the SearchData in SearchResults collections returned by the returned by the *Types* methods so that calling GetMembers with the returned SearchData retrieves Events as well as properties and methods. All events have a native InvokeKind of INVOKE_FUNC. However, events in the SearchResults collection returned by GetMembers will instead have an InvokeKind of INVOKE_EVENTFUNC (a special TLI value) to distinguish events from methods in the same collection. tliStEvents can be specified without tliStClasses to retrieve just classes which have events. tliStEvents returns a a subset of the items in the CoClasses collection.
tliStConstants | Returns all items in the Constants collection which aren't eliminated by the current filters.
tliStDeclarations | Returns all items in the Declarations collection which aren't eliminated by the current filters.
tliStAppObject | A special value indicating that the item represents an application object. It the AppObjString property is set, then this value can be returned by the SearchType property. tliStAppObject can also be passed to the MakeSearchData method. Otherwise, don't pass this value to a SearchType parameter.
tliStRecords | Returns all items in the Records collection which aren't eliminated by the current filters.
tliStIntrinsicAliases | Returns all items in the IntrinsicAliases collection which aren't eliminated by the current filters.
tliStUnions | Returns all items in the Unions collection which aren't eliminated by the current filters.
tliStAll | Contains all of the above flags except tliStAppObject and tliStSearchDefault.


Sorted Property

Applies To

Sorted As Boolean

Read-only property of SearchResults collection which indicates if the collection is currently sorted. Sorted will be True if any method which generates a SearchResults collection is called with the Sorted parameter set to True, or if the Sort method has been called on the collection.


SysKind Property, SysKinds Enum

SysKind Property; SysKinds Enum

Applies To

SysKind As SysKinds

The SysKind property specifies which platform the TypeLibInfo object was built for. The SysKinds enum corresponds to SYSKINDS as defined in the OLE Automation headers. Valid values are SYS_WIN32, SYS_WIN16, and SYS_MAC. You'll rarely see any value returned besides SYS_WIN32.


TypedVariant Property

Applies To

TypedVariant As Variant

If a VarTypeInfo object represents an intrinsic type which is supported by VBA, then this property contains a Variant of the specified type. The return from the TypedVariant property can be passed be the VBA TypeName function to get the VBA string representation of the given type. For example, if VTInfo.VarType is VT_I2, then TypeName(VTInfo.TypedVariant) will return Integer. Note that for VT_ARRAY types, the string returned by TypeName will end with empty parentheses, Integer().

If the VarTypeInfo is a user-defined type or the variant type is not supported by VBA, then TypedVariant has a vartype of VT_EMPTY and TypeName(VTInfo.TypedVariant) is Empty.


TypeInfo, TypeInfoNumber Properties (VarTypeInfo Object)

TypeInfo, TypeInfoNumber Properties

Applies To

TypeInfoNumber As Integer
TypeInfo As TypeInfo

If the VarTypeInfo object represents something other than an intrinsic type (determined using the VarType property), then the TypeInfoNumber property will be >= 0. TypeInfoNumber is the 0-based index of the TypeInfo in its type library. Since type libraries have external links, you must check IsExternalType before relying on TypeInfoNumber to retrieve any information from the current library. If the VarTypeInfo object represents an intrinsic type, then the TypeInfoNumber returns –1, and vice versa. However, you shouldn't used If VTInfo.TypeInfoNumber = -1 without an error trap in place because it is possible that this will raise an error (generally file not found) if an external library isn't installed on the system.

The TypeInfo property is the TypeInfo which corresponds to the TypeInfoNumber. This property is Nothing for intrinsic types. TypeInfoNumber is a much cheaper property that TypeInfo, so only retrieve the object when TypeInfoNumber isn't sufficient.


TypeInfoCount Property

Applies To

TypeInfoCount As Integer

The number of TypeInfo objects available from a TypeLibInfo object. TypeInfoCount is a shortcut for TypeInfos. Count.


TypeInfoNumber Property

Applies To

TypeInfoNumber As Integer

The 0-based number of a TypeInfo in a type library. Since it is much faster to retrieve a TypeInfo object using its number than using its name, the TypeInfoNumber is used extensively by TLI objects. You can translate a TypeInfo Name to a TypeInfoNumber using the GetTypeInfoNumber method.

The TypeInfoNumber is one of the pieces of information available directly from a SearchResults collection returned by all methods in the Applies To list. You can retrieve the TypeInfo object associated with a SearchItem object using the TypeInfos.IndexedItem or GetTypeInfo property. Retrieving the TypeInfoNumber property from SearchResults collection items returned from methods which are not in the Applies To list will raise error tliErrNotApplicable.


TypeKind, TypeKindString Properties, TypeKinds Enum

TypeKind, TypeKindString Properties; TypeKinds Enum

Applies To See Also

TypeKind As TypeKinds
TypeKindString As String

The TypeKind of a TypeInfo gives general information about the type of data contained in the object. TypeKindString is the corresponding string used in ODL/IDL to describe the object. The following table contains the TypeKinds enum name and value, the corresponding string, the TypeInfos collection associated with each type, and a brief description.

# | TypeKind | String | Collection | Description
0 | TKIND_ENUM | enum | Constants | Set of related Long constant values
1 | TKIND_RECORD | record | Records | Ordered data members of intrinsic or defined types
2 | TKIND_MODULE | module | Declarations Constants | List of Dll-declared functions and/or constant values of any type.
3 | TKIND_INTERFACE | interface | Interfaces | Description of an IUnknown derived vtable
4 | TKIND_DISPATCH | dispinterface | Interfaces | Description of an IDispatch derived object. Members are accessible using IDispatch::Invoke only, unless the dispinterface is also dual.
5 | TKIND_COCLASS | coclass | CoClasses | An object which can be created using CoCreateInstance (CreateObject or New in VB). A coclass is a list of interfaces.
6 | TKIND_ALIAS | alias | IntrinsicAliases <All> | An alias to an intrinsic type, or any of the other TypeKinds.
7 | TKIND_UNION | union | Unions | A description of one or more records which can share the same block of memory.
8 | TKIND_MAX | N/A | N/A | Returned by TypeKind if data not available


Value Property

Applies To

Value As Variant

If a MemberInfo object is a constant, then the Value property returns the constant value of the member. Members retrieved from TypeInfo objects with a TypeKind of TKIND_ENUM or TKIND_MODULE and a DescKind of DESCKIND_VARDESC are the only ones which have a value property. If a constant value isn't available, the Value property raises a standard Illegal function call (&H800A0005) error.


VarType Property

VarType Property; TliVarType Enum

Applies To

VarType As TliVarType

The VarType property is the key to the VarTypeInfo object. VarType tells you if you are looking at an intrinsic type, a type library defined type, or an array of either of these. The VarType property has return type TliVarType, which is a duplicate of the VARTYPE enum as defined by OLE Automation. Many of these values correspond to values in the VBA.VbVarType enum. For example, VT_I2 in TliVarType is equivalent to vbInteger in VbVarType.

VarType is returned as a combination of array flags and a base type. Array types are indicated with VT_ARRAY (variable size array) or VT_VECTOR (fixed size or c-style array). Stripping of the array bits will give you the underlying type. If the base type is not VT_EMPTY (0), then the type is intrinsic and you can use the TypedVariant property. If the base type is 0, then the TypeInfo and TypeInfoNumber values are set. See VarTypeInfo for a code snippet.

The VarType property does not necessarily give the variant type as recorded in the type library. TLI automatically resolves any VT_USERDEFINED types into non-intrinsic types, and VT_PTR types are reflected in the PointerLevel and ElementPointerLevel properties.


VTableInterface Property

Applies To

VTableInterface As InterfaceInfo

A TypeInfo frequently has two different views, the VB or OLE Automation view, and the C++ or vtable view. For instance, most interface functions in type libraries have a return type of HRESULT. However, when you ask a MemberInfo object for its ReturnType, you won't get a VT_HRESULT because TLI hides the underlying vtable layout of a TypeInfo from you. If a function in ODL syntax looks like:

HRESULT Stringize([in] long Number, [out, retval] BSTR* retVal);

TLI objects will by default represent this (in VB syntax) as:

Function Stringize(ByVal Number As Long) As String

In order to get the vtable view of InterfaceInfo type TypeInfo object, simply apply the VTableInterface property to switch views on the object. The VTableInterface property may return the tliErrIncompatibleTypeKind error, or Nothing if the TypeKind is compatible, but a vtable interface is not available. Note that the VTableInterface property on a DeclarationInfo type TypeInfo object stored in a TypeInfo type object variable will not return an error even though there is no associated vtable. This property is supported by a DeclarationInfo object to support representing the functions in an unmodified view.

After you've retrieved the InterfaceInfo from the VTableInterface property, you'll see the following changes in the behavior of objects retrieved from this reference:

  • The ReturnType property will generally have a VarType of VT_HRESULT instead of the normal return type for the object.

  • The Count property of the Parameters collection may be one greater than before as the return type mentioned in 1) is now viewed via a ParameterInfo object.

  • MemberInfo objects with an InvokeKind of INVOKE_PROPERTYPUT or INVOKE_PROPERTYPUTREF will similarly have a modified ReturnType and gain a ParameterInfo. as the right-hand side variable is no longer represented as the return value.

  • TypeInfo objects which had a TypeKind of TKIND_DISPATCH will now have a TypeKind of TKIND_INTERFACE. This type of interface is known as a dual interface (TYPEFLAG_FDUAL is set). If there is no vtable support, then a TKIND_DISPATCH TypeInfo object will simply return Nothing from the VTableInterface property.

  • The Members collection for the vtable view of a dual interface will always be smaller than the normal view. When viewed as a TKIND_DISPATCH TypeInfo, members from all base classes are rolled automatically into a single TypeInfo. However, with the vtable view of an object, base members must be retrieved using the ImpliedInterfaces collection, which will have 0 or 1 items in it. Note that the GetMembers, GetMembersWithSubString, and GetMembersWithSubStringEx methods automatically walk base members for TKIND_INTERFACE TypeInfo objects, but Members. GetFilteredMembers walks members only on the immediate TypeInfo.

Example: Return an array of MemberInfo objects order by vtable position

Function OrderedVTableFunctions( _
  ByVal TLInf As TypeLibInfo, _
  IFaceName As String) As TLI.MemberInfo()
Dim TI As InterfaceInfo
Dim Bases As TypeInfos
Dim MI As MemberInfo
Dim OVF() As MemberInfo
Dim MaxOffset As Integer
Dim CurOffset As Integer
  'Make sure we get a VTable interface before proceeding
  On Error Resume Next
  Set TI = TLInf.TypeInfos.NamedItem(IFaceName)
  Set TI = TI.VTableInterface
  If Err Or TI Is Nothing Then Exit Function
  On Error GoTo 0
  With TI.Members
    'Largest VTableOffset is generally on the last
    'member in this collection
    MaxOffset = .Item(.Count).VTableOffset
    ReDim OVF(MaxOffset \ 4)
  End With
  Do Until TI Is Nothing
    'Walk each member
    For Each MI In TI.Members
      CurOffset = MI.VTableOffset
      If CurOffset > MaxOffset Then
        'This is extremely rare
        MaxOffset = CurOffset
        ReDim Preserve OVF(MaxOffset \ 4)
      End If
      Set OVF(CurOffset \ 4) = MI
    Next
    'Get the next base
    Set Bases = TI.ImpliedInterfaces
    Set TI = Nothing
    If Bases.Count Then Set TI = Bases(1)
  Loop
  OrderedVTableFunctions = OVF
End Function

'Calling code
Dim Mems() As MemberInfo
With TLI.TypeLibInfoFromFile("tlbinf32.dll")
  Mems = OrderedVTableFunctions(.Me, "TypeInfos")
End With

See Enhanced OrderedVTableFunctions for a more powerful version of this routine.


VTableOffset Property

Applies To

VTableOffset As Integer

A VTableOffset is available for a MemberInfo object retrieved from an TypeInfo (InterfaceInfo) object which has TypeKind TKIND_INTERFACE, or TypeKind TKIND_DISPATCH and an AttributeMask which contains TYPEFLAG_FDUAL. The VTableOffset corresponds to the offset in bytes of the function pointer for this member in the interface's vtable (virtual function table). The 0-based function number is calculated by dividing the VTableOffset by the size of a pointer (4), so a VTableOffset of 28 corresponds to the 8th function in the vtable.

If the VTableOffset is not available, then this property simply returns –1. No error is thrown. If –1 is returned for an TypeInfo (InterfaceInfo) object which meets the above criteria, then the MemberInfo object was retrieved using GetMember or GetMemberInfo. Since these functions retrieve members based on a MemberId, and a single MemberId can correspond to multiple vtable entries, the VTableOffset property is reliable only when the MemberInfo object is obtained directly from the Members collection.


TLI Errors

The following error values are defined in the TliErrors enum. TLI objects also raise standard OLE Automation or VB (FACILITY_CONTROL) errors. The errors shown here are in the FACILITY_ITF (vbObjectError) range (&H80040000 + some value).

tliErrNoCurrentTypelib (vbObjectError + &H201)
No current typelib. Use the ContainingFile property or LoadRegTypeLib method to load a current typelib.
Raised by almost every TypeLibInfo member except ContainingFile and LoadRegTypeLib.

tliErrCantLoadLibrary (vbObjectError + &H202)
The specified file could not be found, or the file doesn't contain a valid typelib.
Raised by the TypeLibInfo. ContainingFile property.

tliErrTypeLibNotRegistered (vbObjectError + &H203)
No matching typelib is registered, or the registered information is invalid.
Raised by the TypeLibInfo. LoadRegTypeLib method.

tliErrSearchResultsChanged (vbObjectError + &H204)
The parent search object has changed. This reference is no longer valid.
Raised by SearchItem properties if the parent SearchResults collection has been modified.

tliErrNotApplicable (vbObjectError + &H205)
Not applicable to current search results.
Raised by properties of the SearchItem object if the requested property doesn't match the data in the object. For example, getting the MemberId property for an item in a SearchResults collection created by GetTypes will raise this error.

tliErrIncompatibleData (vbObjectError + &H206)
Previous data incompatible with current search.
Raised when two SearchResults objects contain different kinds of data and are required to work together. For example, retrieving a SearchResults object from GetMembersWithSubStringEx and then passing it to the StartResults parameter of the GetTypes method will raise this error.

tliErrIncompatibleSearchType (vbObjectError + &H207)
The requested TypeInfo does not match with the requested search type.
Raised by the MakeSearchData method if the TypeInfoName and SearchType parameters are inconsistent.

tliErrIncompatibleTypeKind (vbObjectError + &H208)
Not applicable for this type of TypeInfo object.
Raised by a member of the TypeInfo object if the TypeKind of the object isn't compatible with the requested information. For example, DefaultInterface will error when called on a TKIND_INTERFACE (InterfaceInfo) object, and VTableInterface will error when called on a TKIND_COCLASS (CoClassInfo) object. Also raised by the GetMemberInfo method.

tliErrInaccessibleImportLib (vbObjectError + &H209)
This TypeInfo refers to an external type library which isn't available through the registry.
Raised if an external type library isn't correctly registered. Can be raised by VTableInterface, GetMember, Members, Interfaces, and GetMemberInfo methods and properties. This error value doesn't cover all cases where this condition occurs. Generally, the low-level type library error for this condition translates into a VB File Not Found error.

tliErrNoDefaultValue (vbObjectError + &H20A)
Default value not specified.
Raised by the ParameterInfo. DefaultValue property if no value is available.

tliErrDataNotAvailable (vbObjectError + &H20B)
For this functionality, the MemberInfo object must be obtained through the Members collection, not GetMember.
The data retrieved by the GetMember property isn't sufficient to provide all information about the member. This error is raised by GetDllEntry, CustomDataCollection, and CallConv members on the MemberInfo object, and CustomDataCollection on the ParameterInfo object. Note that the VTableOffset property returns –1 instead of this error for the same condition.

tliErrNotAnEntryPoint (vbObjectError + &H20C)
DllEntry data is not applicable to this MemberInfo.
Raised by GetDllEntry property if the property isn't applicable.

tliErrStopFiltering (vbObjectError + &H20D)
Raise this error in CustomFilter_Visit to stop filtering.
Used to stop the SearchResults. Filter method before all items have been visited. Raise this error from the CustomFilter_Visit method to terminate the callback sequence.

tliErrArrayBoundsNotAvailable (vbObjectError + &H20E)
Type is not a fixed size array.
Raised by the ArrayBounds method if the array represented by the VarTypeInfo object is not fixed size.

tliErrSearchResultsNotSorted (vbObjectError + &H20F)
SearchResults collection must be sorted.
Raised by the SearchResults. Locate method if the SearchString parameter isn't specified and the collection isn't sorted.

tliErrTypeNotArray (vbObjectError + &H210)
Type not an array.
Raised by the ElementPointerLevel property and ArrayBounds method if the VarTypeInfo object does not represent an array.


TliItemDataTypes Enum

Enum TliItemDataTypes
  tliIdtMemberID,
  tliIdtInvokeKinds
End Enum

Specifies which type of data is placed in the ItemData of the ListBox or ComboBox by the GetMembersDirect or GetFilteredMembersDirect methods. The default value is tliIdtMemberID, which places the MemberId corresponding to the name of the item in the ItemData. tliIdtInvokeKinds instead places the InvokeKinds in the ItemData. Since the MemberId can be retrieved using the name of the member much more easily than the InvokeKinds can be recalculated, tliItdInvokeKinds is recommended if you will be using the GetMemberInfo method to retrieve a MemberInfo item based on the ListBox/ComboBox data.


TliWindowTypes Enum

Applies To

Enum TliWindowTypes
  tliWtListBox,
  tliWtComboBox
End Enum

For methods in the Applies To list, the value of the WindowType parameter, which has type TliWindowTypes, designates if the hWnd parameters specifies is a ListBox or a ComboBox. Since the Windows message values used to manipulate the two window classes are different, it is important to get the WindowType correct. The default is always tliWtListBox.


PrototypeMember Function

The PrototypeMember function generates a description of the specified member function as it would be described in the Visual Basic language. This function uses two helper functions which are shown in other topics, GetSearchType and ProduceDefaultValue. Additional documentation on TLI calls used in this sample is available via hyperlinks in the code.

Function PrototypeMember( _
  TLInf As TypeLibInfo, _
  ByVal SearchData As Long, _
  ByVal InvokeKinds As InvokeKinds, _
  Optional ByVal MemberId As Long = -1, _
  Optional ByVal MemberName As String) As String
Dim pi As ParameterInfo
Dim fFirstParameter As Boolean
Dim fIsConstant As Boolean
Dim fByVal As Boolean
Dim retVal As String
Dim ConstVal As Variant
Dim strTypeName As String
Dim VarTypeCur As Integer
Dim fDefault As Boolean, fOptional As Boolean, fParamArray As Boolean
Dim TIType As TypeInfo
Dim TIResolved As TypeInfo
Dim TKind As TypeKinds
  With TLInf
    fIsConstant = GetSearchType(SearchData) And tliStConstants
    With .GetMemberInfo(SearchData, InvokeKinds, MemberId, MemberName)
      If fIsConstant Then
        retVal = "Const "
      ElseIf InvokeKinds = INVOKE_FUNC Or InvokeKinds = INVOKE_EVENTFUNC Then
        Select Case .ReturnType.VarType
          Case VT_VOID, VT_HRESULT
            retVal = "Sub "
          Case Else
            retVal = "Function "
        End Select
      Else
        retVal = "Property "
      End If
      retVal = retVal & .Name
      With .Parameters
        If .Count Then
          retVal = retVal & "("
          fFirstParameter = True
          fParamArray = .OptionalCount = -1
          For Each pi In .Me
            If Not fFirstParameter Then
              retVal = retVal & ", "
            End If
            fFirstParameter = False
            fDefault = pi.Default
            fOptional = fDefault Or pi.Optional
            If fOptional Then
              If fParamArray Then
                'This will be the only optional parameter
                retVal = retVal & "[ParamArray "
              Else
                retVal = retVal & "["
              End If
            End If
            With pi.VarTypeInfo
              Set TIType = Nothing
              Set TIResolved = Nothing
              TKind = TKIND_MAX
              VarTypeCur = .VarType
              If (VarTypeCur And Not (VT_ARRAY Or VT_VECTOR)) = 0 Then
              'If Not .TypeInfoNumber Then 'This may error, don't use here
                On Error Resume Next
                Set TIType = .TypeInfo
                If Not TIType Is Nothing Then
                  Set TIResolved = TIType
                  TKind = TIResolved.TypeKind
                  Do While TKind = TKIND_ALIAS
                    TKind = TKIND_MAX
                    Set TIResolved = TIResolved.ResolvedType
                    If Err Then
                      Err.Clear
                    Else
                      TKind = TIResolved.TypeKind
                    End If
                  Loop
                End If
                Select Case TKind
                  Case TKIND_INTERFACE, TKIND_COCLASS, TKIND_DISPATCH
                    fByVal = .PointerLevel = 1
                  Case TKIND_RECORD
                    'Records not passed ByVal in VB
                    fByVal = False
                  Case Else
                    fByVal = .PointerLevel = 0
                End Select
                If fByVal Then retVal = retVal & "ByVal "
                retVal = retVal & pi.Name
                If VarTypeCur And (VT_ARRAY Or VT_VECTOR) Then retVal = retVal & "()"
                If TIType Is Nothing Then 'Error
                  retVal = retVal & " As ?"
                Else
                  If .IsExternalType Then
                    retVal = retVal & " As " & _
                             .TypeLibInfoExternal.Name & "." & TIType.Name
                  Else
                    retVal = retVal & " As " & TIType.Name
                  End If
                End If
                On Error GoTo 0
              Else
                If .PointerLevel = 0 Then retVal = retVal & "ByVal "
                retVal = retVal & pi.Name
                If VarTypeCur <> vbVariant Then
                  strTypeName = TypeName(.TypedVariant)
                  If VarTypeCur And (VT_ARRAY Or VT_VECTOR) Then
                    retVal = retVal & "() As " & Left$(strTypeName, Len(strTypeName) - 2)
                  Else
                    retVal = retVal & " As " & strTypeName
                  End If
                End If
              End If
              If fOptional Then
                If fDefault Then
                  retVal = retVal & ProduceDefaultValue(pi.DefaultValue, TIResolved)
                End If
                retVal = retVal & "]"
              End If
            End With
          Next
          retVal = retVal & ")"
        End If
      End With
      If fIsConstant Then
        ConstVal = .Value
        retVal = retVal & " = " & ConstVal
        Select Case VarType(ConstVal)
          Case vbInteger, vbLong
            If ConstVal < 0 Or ConstVal > 15 Then
              retVal = retVal & " (&H" & Hex$(ConstVal) & ")"
            End If
        End Select
      Else
        With .ReturnType
          VarTypeCur = .VarType
          If VarTypeCur = 0 Or (VarTypeCur And Not (VT_ARRAY Or VT_VECTOR)) = 0 Then
          'If Not .TypeInfoNumber Then 'This may error, don't use here
            On Error Resume Next
            If Not .TypeInfo Is Nothing Then
              If Err Then 'Information not available
                retVal = retVal & " As ?"
              Else
                If .IsExternalType Then
                  retVal = retVal & " As " & _
                           .TypeLibInfoExternal.Name & "." & .TypeInfo.Name
                Else
                  retVal = retVal & " As " & .TypeInfo.Name
                End If
              End If
            End If
            If VarTypeCur And (VT_ARRAY Or VT_VECTOR) Then retVal = retVal & "()"
            On Error GoTo 0
          Else
            Select Case VarTypeCur
              Case VT_VARIANT, VT_VOID, VT_HRESULT
              Case Else
                strTypeName = TypeName(.TypedVariant)
                If VarTypeCur And (VT_ARRAY Or VT_VECTOR) Then
                  retVal = retVal & "() As " & Left$(strTypeName, Len(strTypeName) - 2)
                Else
                  retVal = retVal & " As " & strTypeName
                End If
            End Select
          End If
        End With
      End If
      PrototypeMember = retVal & vbCrLf & "  " & _
                        "Member of " & TLInf.Name & "." & _
                        TLInf.GetTypeInfo(SearchData And &HFFFF&).Name & _
                        vbCrLf & "  " & .HelpString
    End With
  End With

End Function


SearchData Expansion Functions

C macros and VB routines to build and dissect a SearchData Long value.

//C macros
#define SEARCHDATA_SEARCHTYPE(sd) ((sd) >> 0x18 & 0xff)
#define SEARCHDATA_TYPEINFONUMBER(sd) ((sd) & 0x1fff)
#define SEARCHDATA_LIBNUM(sd) ((((sd) >> 0xd & 0x7) << 0x8) | ((sd) >> 0x10 & 0xff))
#define SEARCHDATA_HIDDEN(sd) ((sd) & 0x1000)
#define BUILD_SEARCHDATA(tinfo, searchtype, libnum, hidden) \
  (((WORD)(tinfo) & 0x1fff) | \
  ((DWORD)(searchtype) << 0x18) | \
  (((DWORD)(libnum) & 0xff) << 0x10) | \
  (((DWORD)(libnum) & 0x700) << 0x5)) | \
  (hidden ? 0x1000 : 0)

'VB SearchData routines
Function GetSearchType(ByVal SearchData As Long) As TliSearchTypes
  If SearchData And &H80000000 Then
    GetSearchType = ((SearchData And &H7FFFFFFF) \ &H1000000 And &H7F&) Or &H80
  Else
    GetSearchType = SearchData \ &H1000000 And &HFF&
  End If
End Function
Function GetTypeInfoNumber(ByVal SearchData As Long) As Integer
  GetTypeInfoNumber = SearchData And &HFFF&
End Function
Function GetLibNum(ByVal SearchData As Long) As Integer
  SearchData = SearchData And &H7FFFFFFF
  GetLibNum = ((SearchData \ &H2000& And &H7) * &H100&) Or _
               (SearchData \ &H10000 And &HFF&)
End Function
Function GetHidden(ByVal SearchData As Long) As Boolean
    If SearchData And &H1000& Then GetHidden = True
End Function
Function BuildSearchData( _
   ByVal TypeInfoNumber As Integer, _
   ByVal SearchTypes As TliSearchTypes, _
   Optional ByVal LibNum As Integer, _
   Optional ByVal Hidden As Boolean = False) As Long
  If SearchTypes And &H80 Then
    BuildSearchData = _
      (TypeInfoNumber And &H1FFF&) Or _
      ((SearchTypes And &H7F) * &H1000000) Or &H80000000
  Else
    BuildSearchData = _
      (TypeInfoNumber And &H1FFF&) Or _
      (SearchTypes * &H1000000)
  End If

  If LibNum Then
    BuildSearchData = BuildSearchData Or _
      ((LibNum And &HFF) * &H10000) Or _
      ((LibNum And &H700) * &H20&)
  End If
  If Hidden Then
    BuildSearchData = BuildSearchData Or &H1000&
  End If
End Function


Enhanced OrderedVTableFunctions Function

This version of OrderedVTableFunctions routine has additional functionality to the one presented with the VTableInterface topic. In this version, vtable entries from the standard IUnknown and IDispatch base classes are not returned with the function. Instead, a BaseType parameter returns the type of the base.

Private Const strIID_IDispatch As String = "{00020400-0000-0000-C000-000000000046}"
Private Const strIID_IUnknown As String = "{00000000-0000-0000-C000-000000000046}"

Enum BaseType
  btNone
  btIUnknown
  btIDispatch
End Enum

Function OrderedVTableFunctions( _
  ByVal TLInf As TypeLibInfo, _
  IFaceName As String, _
  BaseType As BaseType) As TLI.MemberInfo()
Dim TI As InterfaceInfo
Dim TIStart As InterfaceInfo
Dim Bases As TypeInfos
Dim MI As MemberInfo
Dim iStandardEntries As Integer
Dim iProcessed As Integer
Dim fCheckDispatch As Boolean
Dim OVF() As MemberInfo
Dim MaxOffset As Integer
Dim CurOffset As Integer
  'Make sure we get a VTable interface before proceeding
  On Error Resume Next
  Set TI = TLInf.TypeInfos.NamedItem(IFaceName)
  Set TI = TI.VTableInterface
  If Err Or TI Is Nothing Then Exit Function
  On Error GoTo 0
  'To avoid retrieving the standard IDispatch and
  'IUnknown vtable entries on every call, first
  'walk the base interfaces to figure out if we
  'derived from IDispatch/IUnknown
  If TI.AttributeMask And TYPEFLAG_FDUAL Then
    BaseType = btIDispatch
    iStandardEntries = 7
    fCheckDispatch = True
  Else
    Set TIStart = TI
    BaseType = btNone
    Do Until TI Is Nothing
      iProcessed = iProcessed + 1
      Set Bases = TI.ImpliedInterfaces
      Set TI = Nothing
      If Bases.Count Then
        Set TI = Bases(1)
        If TI.Guid = strIID_IDispatch Then
          BaseType = btIDispatch
          Set TI = TIStart
          iStandardEntries = 7
          Exit Do
        ElseIf TI.Guid = strIID_IUnknown Then
          BaseType = btIUnknown
          iStandardEntries = 3
          Exit Do
        End If
      End If
    Loop
    Set TI = TIStart
  End If
  With TI.Members
    'Largest VTableOffset is generally on the last
    'member in this collection
    MaxOffset = .Item(.Count).VTableOffset
    ReDim OVF((MaxOffset \ 4) - iStandardEntries)
  End With
  Do Until TI Is Nothing
    'Walk each member
    For Each MI In TI.Members
      CurOffset = MI.VTableOffset
      If CurOffset > MaxOffset Then
        'This is extremely rare
        MaxOffset = CurOffset
        ReDim Preserve OVF((MaxOffset \ 4) - iStandardEntries)
      End If
      Set OVF((CurOffset \ 4) - iStandardEntries) = MI
    Next
    'Get the next base
    If fCheckDispatch Then
      Set Bases = TI.ImpliedInterfaces
      Set TI = Nothing
      If Bases.Count Then
        Set TI = Bases(1)
        If TI.Guid = strIID_IDispatch Then
          Exit Do
        End If
      End If
    Else
      iProcessed = iProcessed - 1
      If iProcessed = 0 Then Exit Do
      Set TI = TI.ImpliedInterfaces(1)
    End If
  Loop
  OrderedVTableFunctions = OVF
End Function


Using TLI with C++

All comments here are based on using TLI objects via the provided header file.

Creating a TLI object can be accomplished using the provided wrapper classes. The TLIApplication object is created automatically in VB, but must be done explicitly in C++. If a code sample in this help file uses TLI.<TLIMethod> or simply <TLIMethod>, then you will have to call this method off of an explicit TLIApplication reference in C++. The following code shows how to create a TLIApplication object and calls the TypeLibInfoFromFile method. TypeLibInfo and SearchHelper objects also have C* classes provided and can be created directly. All other types are returned from methods off of these objects.

BSTR bstrFile;
CTLIApplication TLIApp;
TypeLibInfo *pTLInf;
HRESULT hr;
if (SUCCEEDED(hr = TLIApp.LaunchError()) &&
    SUCCEEDED(hr = TLIApp->TypeLibInfoFromFile(bstrFile, &pTLInf)))
{
  //You have a TypeLibInfo object
  pTLInf->Release();
}

Many of the TLI methods use default parameter values. These parameters are routinely omitted in the samples when the default value is sufficient. However, the function descriptions in each topic indicate the default values. You can also use the VB object browser to see the defaults, or build your own standalone browser with TLI.

When using the StartResults parameter of any method which returns a SearchResults collection, you must take care to correctly release the collection. If you pass an address to a reference to the same SearchResults object as both the StartResults and retVal parameters, then the reference returned in retVal will be the StartResults reference, which now has as an additional reference count on it.


C++ Header File

#ifndef _TLBINF_H_
#define _TLBINF_H_
interface CoClasses;
interface CoClassInfo;
interface ConstantInfo;
interface Constants;
interface CustomData;
interface CustomDataCollection;
interface CustomFilter;
interface CustomSort;
interface DeclarationInfo;
interface Declarations;
interface InterfaceInfo;
interface Interfaces;
interface IntrinsicAliases;
interface IntrinsicAliasInfo;
interface ListBoxNotification;
interface MemberInfo;
interface Members;
interface ParameterInfo;
interface Parameters;
interface RecordInfo;
interface Records;
interface _SearchHelper;
interface SearchItem;
interface SearchResults;
interface _TLIApplication;
interface TypeInfo;
interface TypeInfos;
interface _TypeLibInfo;
interface UnionInfo;
interface Unions;
interface VarTypeInfo;
#define TypeLibInfo _TypeLibInfo
#define TLIApplication _TLIApplication
#define SearchHelper _SearchHelper

enum TliErrors {
  tliErrNoCurrentTypelib=-2147220991,
  tliErrCantLoadLibrary=-2147220990,
  tliErrTypeLibNotRegistered=-2147220989,
  tliErrSearchResultsChanged=-2147220988,
  tliErrNotApplicable=-2147220987,
  tliErrIncompatibleData=-2147220986,
  tliErrIncompatibleSearchType=-2147220985,
  tliErrIncompatibleTypeKind=-2147220984,
  tliErrInaccessibleImportLib=-2147220983,
  tliErrNoDefaultValue=-2147220982,
  tliErrDataNotAvailable=-2147220981,
  tliErrNotAnEntryPoint=-2147220980,
  tliErrStopFiltering=-2147220979,
  tliErrArrayBoundsNotAvailable=-2147220978,
  tliErrTypeNotArray=-2147220977
};

typedef TYPEFLAGS TypeFlags;
#define TYPEFLAG_NONE 0

//typedef IMPLTYPEFLAGS ImplTypeFlags;

typedef TYPEKIND TypeKinds;

typedef FUNCFLAGS FuncFlags;
#define FUNCFLAG_NONE 0

typedef VARFLAGS VarFlags;
#define VARCFLAG_NONE 0

typedef SYSKIND SysKinds;

typedef LIBFLAGS LibFlags;

typedef INVOKEKIND InvokeKinds;
#define INVOKE_UNKNOWN 0
#define INVOKE_EVENTFUNC 0x10
#define INVOKE_CONST 0x20

typedef ULONG ParamFlags;

typedef DESCKIND DescKinds;

typedef VARTYPE TliVarType;

enum _TliSearchTypes {
  tliStDefault=4096,
  tliStClasses=1,
  tliStEvents=2,
  tliStConstants=4,
  tliStDeclarations=8,
  tliStAppObject=16,
  tliStRecords=32,
  tliStIntrinsicAliases=64,
  tliStUnions=128,
  tliStAll=239
};
typedef DWORD TliSearchTypes;

enum TliWindowTypes {
  tliWtListBox=0,
  tliWtComboBox=1
};

enum TliItemDataTypes {
  tliIdtMemberID=0,
  tliIdtInvokeKinds=1
};

enum TliCustomFilterAction {
  tliCfaLeave=0,
  tliCfaDuplicate=1,
  tliCfaExtract=2,
  tliCfaDelete=3
};

#define SEARCHDATA_SEARCHTYPE(sd) ((sd) >> 0x18 & 0xff)
#define SEARCHDATA_TYPEINFO(sd) ((sd) & 0x1fff)
#define SEARCHDATA_LIBNUM(sd) ((((sd) >> 0xd & 0x7) << 0x8) | ((sd) >> 0x10 & 0xff))
#define MAKE_SEARCHDATA(tinfo, libnum, searchtype) (((WORD)(tinfo) & 0x1fff) | \
  ((DWORD)(searchtype) << 0x18) | \
  (((DWORD)(libnum) & 0xff) << 0x10) | \
  (((DWORD)(libnum) & 0x700) << 0x5))

DEFINE_GUID(IID_CoClasses,0x8B217744L,0x717D,0x11CE,0xAB,0x5B,0xD4,0x12,0x03,0xC1,0x00,0x00);
DECLARE_INTERFACE_(CoClasses, IDispatch)
{
    STDMETHOD(Me)(THIS_ TypeInfos FAR* FAR* retVal) PURE;
    STDMETHOD(_placeholder_destructor)(THIS) PURE;
    STDMETHOD(_NewEnum)(THIS_ LPUNKNOWN FAR* retVal) PURE;
    STDMETHOD(get_Count)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_Item)(THIS_ short Index, CoClassInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_IndexedItem)(THIS_ short TypeInfoNumber, CoClassInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_NamedItem)(THIS_ BSTR FAR* TypeInfoName, CoClassInfo FAR* FAR* retVal) PURE;
};

DEFINE_GUID(IID_CoClassInfo,0x8B217743L,0x717D,0x11CE,0xAB,0x5B,0xD4,0x12,0x03,0xC1,0x00,0x00);
DECLARE_INTERFACE_(CoClassInfo, IDispatch)
{
    STDMETHOD(Me)(THIS_ CoClassInfo FAR* FAR* retVal) PURE;
    STDMETHOD(_placeholder_destructor)(THIS) PURE;
    STDMETHOD(get_Name)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get_GUID)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get__OldHelpString)(THIS) PURE;
    STDMETHOD(get_HelpContext)(THIS_ long FAR* retVal) PURE;
    STDMETHOD(get_HelpFile)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get_AttributeMask)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_AttributeStrings)(THIS_ LPSAFEARRAY FAR* AttributeArray, short FAR* retVal) PURE;
    STDMETHOD(get__OldTypeKind)(THIS) PURE;
    STDMETHOD(get_TypeKindString)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get_TypeInfoNumber)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(_placeholder_VTableInterface)(THIS) PURE;
    STDMETHOD(_placeholder_GetMember)(THIS) PURE;
    STDMETHOD(_placeholder_Members)(THIS) PURE;
    STDMETHOD(get_Parent)(THIS_ TypeLibInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_Interfaces)(THIS_ Interfaces FAR* FAR* retVal) PURE;
    STDMETHOD(get_DefaultInterface)(THIS_ InterfaceInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_DefaultEventInterface)(THIS_ InterfaceInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_TypeKind)(THIS_ TypeKinds FAR* retVal) PURE;
    STDMETHOD(get_ResolvedType)(THIS_ VarTypeInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_CustomDataCollection)(THIS_ CustomDataCollection FAR* FAR* retVal) PURE;
    STDMETHOD(get_HelpString)(THIS_ long LCID, BSTR FAR* retVal) PURE;
    STDMETHOD(get_ITypeInfo)(THIS_ LPUNKNOWN FAR* retVal) PURE;
    STDMETHOD(get_MajorVersion)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_MinorVersion)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_HelpStringDll)(THIS_ long LCID, BSTR FAR* retVal) PURE;
    STDMETHOD(get_HelpStringContext)(THIS_ long FAR* retVal) PURE;
};

DEFINE_GUID(IID_ConstantInfo,0x8B21774DL,0x717D,0x11CE,0xAB,0x5B,0xD4,0x12,0x03,0xC1,0x00,0x00);
DECLARE_INTERFACE_(ConstantInfo, IDispatch)
{
    STDMETHOD(Me)(THIS_ TypeInfo FAR* FAR* retVal) PURE;
    STDMETHOD(_placeholder_destructor)(THIS) PURE;
    STDMETHOD(get_Name)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get_GUID)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get__OldHelpString)(THIS) PURE;
    STDMETHOD(get_HelpContext)(THIS_ long FAR* retVal) PURE;
    STDMETHOD(get_HelpFile)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get_AttributeMask)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_AttributeStrings)(THIS_ LPSAFEARRAY FAR* AttributeArray, short FAR* retVal) PURE;
    STDMETHOD(get__OldTypeKind)(THIS) PURE;
    STDMETHOD(get_TypeKindString)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get_TypeInfoNumber)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(_placeholder_VTableInterface)(THIS) PURE;
    STDMETHOD(get_GetMember)(THIS_ VARIANT Index, MemberInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_Members)(THIS_ Members FAR* FAR* retVal) PURE;
    STDMETHOD(get_Parent)(THIS_ TypeLibInfo FAR* FAR* retVal) PURE;
    STDMETHOD(_ImpliedInterfaces)(THIS) PURE;
    STDMETHOD(_DefaultInterface)(THIS) PURE;
    STDMETHOD(_DefaultEventInterface)(THIS) PURE;
    STDMETHOD(get_TypeKind)(THIS_ TypeKinds FAR* retVal) PURE;
    STDMETHOD(get_ResolvedType)(THIS_ VarTypeInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_CustomDataCollection)(THIS_ CustomDataCollection FAR* FAR* retVal) PURE;
    STDMETHOD(get_HelpString)(THIS_ long LCID, BSTR FAR* retVal) PURE;
    STDMETHOD(get_ITypeInfo)(THIS_ LPUNKNOWN FAR* retVal) PURE;
    STDMETHOD(get_MajorVersion)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_MinorVersion)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_HelpStringDll)(THIS_ long LCID, BSTR FAR* retVal) PURE;
    STDMETHOD(get_HelpStringContext)(THIS_ long FAR* retVal) PURE;
};

DEFINE_GUID(IID_Constants,0x8B21774CL,0x717D,0x11CE,0xAB,0x5B,0xD4,0x12,0x03,0xC1,0x00,0x00);
DECLARE_INTERFACE_(Constants, IDispatch)
{
    STDMETHOD(Me)(THIS_ TypeInfos FAR* FAR* retVal) PURE;
    STDMETHOD(_placeholder_destructor)(THIS) PURE;
    STDMETHOD(_NewEnum)(THIS_ LPUNKNOWN FAR* retVal) PURE;
    STDMETHOD(get_Count)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_Item)(THIS_ short Index, ConstantInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_IndexedItem)(THIS_ short TypeInfoNumber, ConstantInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_NamedItem)(THIS_ BSTR FAR* TypeInfoName, ConstantInfo FAR* FAR* retVal) PURE;
};

DEFINE_GUID(IID_CustomData,0x8B217763L,0x717D,0x11CE,0xAB,0x5B,0xD4,0x12,0x03,0xC1,0x00,0x00);
DECLARE_INTERFACE_(CustomData, IDispatch)
{
    STDMETHOD(Me)(THIS_ CustomData FAR* FAR* retVal) PURE;
    STDMETHOD(_placeholder_destructor)(THIS) PURE;
    STDMETHOD(get_GUID)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get_Value)(THIS_ VARIANT FAR* retVal) PURE;
};

DEFINE_GUID(IID_CustomDataCollection,0x8B217764L,0x717D,0x11CE,0xAB,0x5B,0xD4,0x12,0x03,0xC1,0x00,0x00);
DECLARE_INTERFACE_(CustomDataCollection, IDispatch)
{
    STDMETHOD(Me)(THIS_ CustomDataCollection FAR* FAR* retVal) PURE;
    STDMETHOD(_placeholder_destructor)(THIS) PURE;
    STDMETHOD(_NewEnum)(THIS_ LPUNKNOWN FAR* retVal) PURE;
    STDMETHOD(get_Item)(THIS_ short Index, CustomData FAR* FAR* retVal) PURE;
    STDMETHOD(get_Count)(THIS_ short FAR* retVal) PURE;
};

DEFINE_GUID(IID_CustomFilter,0x8B217760L,0x717D,0x11CE,0xAB,0x5B,0xD4,0x12,0x03,0xC1,0x00,0x00);
DECLARE_INTERFACE_(CustomFilter, IDispatch)
{
    STDMETHOD(Visit)(THIS_ SearchItem FAR* Item, TliCustomFilterAction FAR* Action) PURE;
};

DEFINE_GUID(IID_CustomSort,0x8B21775FL,0x717D,0x11CE,0xAB,0x5B,0xD4,0x12,0x03,0xC1,0x00,0x00);
DECLARE_INTERFACE_(CustomSort, IDispatch)
{
    STDMETHOD(Compare)(THIS_ SearchItem FAR* Item1, SearchItem FAR* Item2, long FAR* Compare) PURE;
};

DEFINE_GUID(IID_DeclarationInfo,0x8B21774FL,0x717D,0x11CE,0xAB,0x5B,0xD4,0x12,0x03,0xC1,0x00,0x00);
DECLARE_INTERFACE_(DeclarationInfo, IDispatch)
{
    STDMETHOD(Me)(THIS_ DeclarationInfo FAR* FAR* retVal) PURE;
    STDMETHOD(_placeholder_destructor)(THIS) PURE;
    STDMETHOD(get_Name)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get_GUID)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get__OldHelpString)(THIS) PURE;
    STDMETHOD(get_HelpContext)(THIS_ long FAR* retVal) PURE;
    STDMETHOD(get_HelpFile)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get_AttributeMask)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_AttributeStrings)(THIS_ LPSAFEARRAY FAR* AttributeArray, short FAR* retVal) PURE;
    STDMETHOD(get__OldTypeKind)(THIS) PURE;
    STDMETHOD(get_TypeKindString)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get_TypeInfoNumber)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(_placeholder_VTableInterface)(THIS) PURE;
    STDMETHOD(get_GetMember)(THIS_ VARIANT Index, MemberInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_Members)(THIS_ Members FAR* FAR* retVal) PURE;
    STDMETHOD(get_Parent)(THIS_ TypeLibInfo FAR* FAR* retVal) PURE;
    STDMETHOD(_ImpliedInterfaces)(THIS) PURE;
    STDMETHOD(_DefaultInterface)(THIS) PURE;
    STDMETHOD(_DefaultEventInterface)(THIS) PURE;
    STDMETHOD(get_TypeKind)(THIS_ TypeKinds FAR* retVal) PURE;
    STDMETHOD(get_ResolvedType)(THIS_ VarTypeInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_CustomDataCollection)(THIS_ CustomDataCollection FAR* FAR* retVal) PURE;
    STDMETHOD(get_HelpString)(THIS_ long LCID, BSTR FAR* retVal) PURE;
    STDMETHOD(get_ITypeInfo)(THIS_ LPUNKNOWN FAR* retVal) PURE;
    STDMETHOD(get_MajorVersion)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_MinorVersion)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_HelpStringDll)(THIS_ long LCID, BSTR FAR* retVal) PURE;
    STDMETHOD(get_HelpStringContext)(THIS_ long FAR* retVal) PURE;
};

DEFINE_GUID(IID_Declarations,0x8B21774EL,0x717D,0x11CE,0xAB,0x5B,0xD4,0x12,0x03,0xC1,0x00,0x00);
DECLARE_INTERFACE_(Declarations, IDispatch)
{
    STDMETHOD(Me)(THIS_ TypeInfos FAR* FAR* retVal) PURE;
    STDMETHOD(_placeholder_destructor)(THIS) PURE;
    STDMETHOD(_NewEnum)(THIS_ LPUNKNOWN FAR* retVal) PURE;
    STDMETHOD(get_Count)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_Item)(THIS_ short Index, DeclarationInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_IndexedItem)(THIS_ short TypeInfoNumber, DeclarationInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_NamedItem)(THIS_ BSTR FAR* TypeInfoName, DeclarationInfo FAR* FAR* retVal) PURE;
};

DEFINE_GUID(IID_InterfaceInfo,0x8B217741L,0x717D,0x11CE,0xAB,0x5B,0xD4,0x12,0x03,0xC1,0x00,0x00);
DECLARE_INTERFACE_(InterfaceInfo, IDispatch)
{
    STDMETHOD(Me)(THIS_ InterfaceInfo FAR* FAR* retVal) PURE;
    STDMETHOD(_placeholder_destructor)(THIS) PURE;
    STDMETHOD(get_Name)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get_GUID)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get__OldHelpString)(THIS) PURE;
    STDMETHOD(get_HelpContext)(THIS_ long FAR* retVal) PURE;
    STDMETHOD(get_HelpFile)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get_AttributeMask)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_AttributeStrings)(THIS_ LPSAFEARRAY FAR* AttributeArray, short FAR* retVal) PURE;
    STDMETHOD(get__OldTypeKind)(THIS) PURE;
    STDMETHOD(get_TypeKindString)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get_TypeInfoNumber)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_VTableInterface)(THIS_ InterfaceInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_GetMember)(THIS_ VARIANT Index, MemberInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_Members)(THIS_ Members FAR* FAR* retVal) PURE;
    STDMETHOD(get_Parent)(THIS_ TypeLibInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_ImpliedInterfaces)(THIS_ Interfaces FAR* FAR* retVal) PURE;
    STDMETHOD(_DefaultInterface)(THIS) PURE;
    STDMETHOD(_DefaultEventInterface)(THIS) PURE;
    STDMETHOD(get_TypeKind)(THIS_ TypeKinds FAR* retVal) PURE;
    STDMETHOD(get_ResolvedType)(THIS_ VarTypeInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_CustomDataCollection)(THIS_ CustomDataCollection FAR* FAR* retVal) PURE;
    STDMETHOD(get_HelpString)(THIS_ long LCID, BSTR FAR* retVal) PURE;
    STDMETHOD(get_ITypeInfo)(THIS_ LPUNKNOWN FAR* retVal) PURE;
    STDMETHOD(get_MajorVersion)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_MinorVersion)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_HelpStringDll)(THIS_ long LCID, BSTR FAR* retVal) PURE;
    STDMETHOD(get_HelpStringContext)(THIS_ long FAR* retVal) PURE;
};

DEFINE_GUID(IID_Interfaces,0x8B217742L,0x717D,0x11CE,0xAB,0x5B,0xD4,0x12,0x03,0xC1,0x00,0x00);
DECLARE_INTERFACE_(Interfaces, IDispatch)
{
    STDMETHOD(Me)(THIS_ TypeInfos FAR* FAR* retVal) PURE;
    STDMETHOD(_placeholder_destructor)(THIS) PURE;
    STDMETHOD(_NewEnum)(THIS_ LPUNKNOWN FAR* retVal) PURE;
    STDMETHOD(get_Count)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_Item)(THIS_ short Index, InterfaceInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_IndexedItem)(THIS_ short TypeInfoNumber, InterfaceInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_NamedItem)(THIS_ BSTR FAR* TypeInfoName, InterfaceInfo FAR* FAR* retVal) PURE;
};

DEFINE_GUID(IID_IntrinsicAliases,0x8B217762L,0x717D,0x11CE,0xAB,0x5B,0xD4,0x12,0x03,0xC1,0x00,0x00);
DECLARE_INTERFACE_(IntrinsicAliases, IDispatch)
{
    STDMETHOD(Me)(THIS_ TypeInfos FAR* FAR* retVal) PURE;
    STDMETHOD(_placeholder_destructor)(THIS) PURE;
    STDMETHOD(_NewEnum)(THIS_ LPUNKNOWN FAR* retVal) PURE;
    STDMETHOD(get_Count)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_Item)(THIS_ short Index, IntrinsicAliasInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_IndexedItem)(THIS_ short TypeInfoNumber, IntrinsicAliasInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_NamedItem)(THIS_ BSTR FAR* TypeInfoName, IntrinsicAliasInfo FAR* FAR* retVal) PURE;
};

DEFINE_GUID(IID_IntrinsicAliasInfo,0x8B217761L,0x717D,0x11CE,0xAB,0x5B,0xD4,0x12,0x03,0xC1,0x00,0x00);
DECLARE_INTERFACE_(IntrinsicAliasInfo, IDispatch)
{
    STDMETHOD(Me)(THIS_ IntrinsicAliasInfo FAR* FAR* retVal) PURE;
    STDMETHOD(_placeholder_destructor)(THIS) PURE;
    STDMETHOD(get_Name)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get_GUID)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get__OldHelpString)(THIS) PURE;
    STDMETHOD(get_HelpContext)(THIS_ long FAR* retVal) PURE;
    STDMETHOD(get_HelpFile)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get_AttributeMask)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_AttributeStrings)(THIS_ LPSAFEARRAY FAR* AttributeArray, short FAR* retVal) PURE;
    STDMETHOD(get__OldTypeKind)(THIS) PURE;
    STDMETHOD(get_TypeKindString)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get_TypeInfoNumber)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(_placeholder_VTableInterface)(THIS) PURE;
    STDMETHOD(_placeholder_GetMember)(THIS) PURE;
    STDMETHOD(_placeholder_Members)(THIS) PURE;
    STDMETHOD(get_Parent)(THIS_ TypeLibInfo FAR* FAR* retVal) PURE;
    STDMETHOD(_ImpliedInterfaces)(THIS) PURE;
    STDMETHOD(_DefaultInterface)(THIS) PURE;
    STDMETHOD(_DefaultEventInterface)(THIS) PURE;
    STDMETHOD(get_TypeKind)(THIS_ TypeKinds FAR* retVal) PURE;
    STDMETHOD(get_ResolvedType)(THIS_ VarTypeInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_CustomDataCollection)(THIS_ CustomDataCollection FAR* FAR* retVal) PURE;
    STDMETHOD(get_HelpString)(THIS_ long LCID, BSTR FAR* retVal) PURE;
    STDMETHOD(get_ITypeInfo)(THIS_ LPUNKNOWN FAR* retVal) PURE;
    STDMETHOD(get_MajorVersion)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_MinorVersion)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_HelpStringDll)(THIS_ long LCID, BSTR FAR* retVal) PURE;
    STDMETHOD(get_HelpStringContext)(THIS_ long FAR* retVal) PURE;
};

DEFINE_GUID(IID_ListBoxNotification,0x8B217758L,0x717D,0x11CE,0xAB,0x5B,0xD4,0x12,0x03,0xC1,0x00,0x00);
DECLARE_INTERFACE_(ListBoxNotification, IDispatch)
{
    STDMETHOD(OnAddString)(THIS_ long lpstr, VARIANT_BOOL fUnicode) PURE;
};

DEFINE_GUID(IID_MemberInfo,0x8B217747L,0x717D,0x11CE,0xAB,0x5B,0xD4,0x12,0x03,0xC1,0x00,0x00);
DECLARE_INTERFACE_(MemberInfo, IDispatch)
{
    STDMETHOD(Me)(THIS_ MemberInfo FAR* FAR* retVal) PURE;
    STDMETHOD(_placeholder_destructor)(THIS) PURE;
    STDMETHOD(get_Name)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get__OldHelpString)(THIS) PURE;
    STDMETHOD(get_HelpContext)(THIS_ long FAR* retVal) PURE;
    STDMETHOD(get_HelpFile)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get_Parameters)(THIS_ Parameters FAR* FAR* retVal) PURE;
    STDMETHOD(get_ReturnType)(THIS_ VarTypeInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_AttributeMask)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_AttributeStrings)(THIS_ LPSAFEARRAY FAR* AttributeArray, short FAR* retVal) PURE;
    STDMETHOD(get__OldDescKind)(THIS) PURE;
    STDMETHOD(get_Value)(THIS_ VARIANT FAR* retVal) PURE;
    STDMETHOD(get_MemberId)(THIS_ long FAR* retVal) PURE;
    STDMETHOD(get_VTableOffset)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_InvokeKind)(THIS_ InvokeKinds FAR* retVal) PURE;
    STDMETHOD(get_CustomDataCollection)(THIS_ CustomDataCollection FAR* FAR* retVal) PURE;
    STDMETHOD(get_DescKind)(THIS_ DescKinds FAR* retVal) PURE;
    STDMETHOD(GetDllEntry)(THIS_ BSTR FAR* DllName, BSTR FAR* EntryName, short FAR* Ordinal) PURE;
    STDMETHOD(get_HelpString)(THIS_ long LCID, BSTR FAR* retVal) PURE;
    STDMETHOD(get_HelpStringDll)(THIS_ long LCID, BSTR FAR* retVal) PURE;
    STDMETHOD(get_HelpStringContext)(THIS_ long FAR* retVal) PURE;
    STDMETHOD(get_CallConv)(THIS_  CALLCONV FAR* retVal) PURE;
};

DEFINE_GUID(IID_Members,0x8B217748L,0x717D,0x11CE,0xAB,0x5B,0xD4,0x12,0x03,0xC1,0x00,0x00);
DECLARE_INTERFACE_(Members, IDispatch)
{
    STDMETHOD(Me)(THIS_ Members FAR* FAR* retVal) PURE;
    STDMETHOD(_placeholder_destructor)(THIS) PURE;
    STDMETHOD(_NewEnum)(THIS_ LPUNKNOWN FAR* retVal) PURE;
    STDMETHOD(get_Item)(THIS_ short Index, MemberInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_Count)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(put_FuncFilter)(THIS_ FuncFlags retVal) PURE;
    STDMETHOD(get_FuncFilter)(THIS_ FuncFlags FAR* retVal) PURE;
    STDMETHOD(put_VarFilter)(THIS_ VarFlags retVal) PURE;
    STDMETHOD(get_VarFilter)(THIS_ VarFlags FAR* retVal) PURE;
    STDMETHOD(_OldFillList)(THIS) PURE;
    STDMETHOD(get_GetFilteredMembers)(THIS_ VARIANT_BOOL ShowUnderscore, SearchResults FAR* FAR* retVal) PURE;
    STDMETHOD(GetFilteredMembersDirect)(THIS_ int hWnd, TliWindowTypes WindowType, TliItemDataTypes ItemDataType, VARIANT_BOOL ShowUnderscore, short FAR* retVal) PURE;
};

DEFINE_GUID(IID_ParameterInfo,0x8B217749L,0x717D,0x11CE,0xAB,0x5B,0xD4,0x12,0x03,0xC1,0x00,0x00);
DECLARE_INTERFACE_(ParameterInfo, IDispatch)
{
    STDMETHOD(Me)(THIS_ ParameterInfo FAR* FAR* retVal) PURE;
    STDMETHOD(_placeholder_destructor)(THIS) PURE;
    STDMETHOD(get_Name)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get_Optional)(THIS_ VARIANT_BOOL FAR* retVal) PURE;
    STDMETHOD(get__OldFlags)(THIS) PURE;
    STDMETHOD(get_VarTypeInfo)(THIS_ VarTypeInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_Default)(THIS_ VARIANT_BOOL FAR* retVal) PURE;
    STDMETHOD(get_DefaultValue)(THIS_ VARIANT FAR* retVal) PURE;
    STDMETHOD(get_HasCustomData)(THIS_ VARIANT_BOOL FAR* retVal) PURE;
    STDMETHOD(get_CustomDataCollection)(THIS_ CustomDataCollection FAR* FAR* retVal) PURE;
    STDMETHOD(get_Flags)(THIS_ ParamFlags FAR* retVal) PURE;
};

DEFINE_GUID(IID_Parameters,0x8B21774AL,0x717D,0x11CE,0xAB,0x5B,0xD4,0x12,0x03,0xC1,0x00,0x00);
DECLARE_INTERFACE_(Parameters, IDispatch)
{
    STDMETHOD(Me)(THIS_ Parameters FAR* FAR* retVal) PURE;
    STDMETHOD(_placeholder_destructor)(THIS) PURE;
    STDMETHOD(_NewEnum)(THIS_ LPUNKNOWN FAR* retVal) PURE;
    STDMETHOD(get_Item)(THIS_ short Index, ParameterInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_Count)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_OptionalCount)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_DefaultCount)(THIS_ short FAR* retVal) PURE;
};

DEFINE_GUID(IID_RecordInfo,0x8B21775BL,0x717D,0x11CE,0xAB,0x5B,0xD4,0x12,0x03,0xC1,0x00,0x00);
DECLARE_INTERFACE_(RecordInfo, IDispatch)
{
    STDMETHOD(Me)(THIS_ TypeInfo FAR* FAR* retVal) PURE;
    STDMETHOD(_placeholder_destructor)(THIS) PURE;
    STDMETHOD(get_Name)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get_GUID)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get__OldHelpString)(THIS) PURE;
    STDMETHOD(get_HelpContext)(THIS_ long FAR* retVal) PURE;
    STDMETHOD(get_HelpFile)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get_AttributeMask)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_AttributeStrings)(THIS_ LPSAFEARRAY FAR* AttributeArray, short FAR* retVal) PURE;
    STDMETHOD(get__OldTypeKind)(THIS) PURE;
    STDMETHOD(get_TypeKindString)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get_TypeInfoNumber)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(_placeholder_VTableInterface)(THIS) PURE;
    STDMETHOD(get_GetMember)(THIS_ VARIANT Index, MemberInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_Members)(THIS_ Members FAR* FAR* retVal) PURE;
    STDMETHOD(get_Parent)(THIS_ TypeLibInfo FAR* FAR* retVal) PURE;
    STDMETHOD(_ImpliedInterfaces)(THIS) PURE;
    STDMETHOD(_DefaultInterface)(THIS) PURE;
    STDMETHOD(_DefaultEventInterface)(THIS) PURE;
    STDMETHOD(get_TypeKind)(THIS_ TypeKinds FAR* retVal) PURE;
    STDMETHOD(get_ResolvedType)(THIS_ VarTypeInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_CustomDataCollection)(THIS_ CustomDataCollection FAR* FAR* retVal) PURE;
    STDMETHOD(get_HelpString)(THIS_ long LCID, BSTR FAR* retVal) PURE;
    STDMETHOD(get_ITypeInfo)(THIS_ LPUNKNOWN FAR* retVal) PURE;
    STDMETHOD(get_MajorVersion)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_MinorVersion)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_HelpStringDll)(THIS_ long LCID, BSTR FAR* retVal) PURE;
    STDMETHOD(get_HelpStringContext)(THIS_ long FAR* retVal) PURE;
};

DEFINE_GUID(IID_Records,0x8B21775CL,0x717D,0x11CE,0xAB,0x5B,0xD4,0x12,0x03,0xC1,0x00,0x00);
DECLARE_INTERFACE_(Records, IDispatch)
{
    STDMETHOD(Me)(THIS_ TypeInfos FAR* FAR* retVal) PURE;
    STDMETHOD(_placeholder_destructor)(THIS) PURE;
    STDMETHOD(_NewEnum)(THIS_ LPUNKNOWN FAR* retVal) PURE;
    STDMETHOD(get_Count)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_Item)(THIS_ short Index, RecordInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_IndexedItem)(THIS_ short TypeInfoNumber, RecordInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_NamedItem)(THIS_ BSTR FAR* TypeInfoName, RecordInfo FAR* FAR* retVal) PURE;
};

DEFINE_GUID(IID__SearchHelper,0x8B217751L,0x717D,0x11CE,0xAB,0x5B,0xD4,0x12,0x03,0xC1,0x00,0x00);
DECLARE_INTERFACE_(_SearchHelper, IDispatch)
{
    STDMETHOD(Me)(THIS_ TypeLibInfo FAR* FAR* retVal) PURE;
    STDMETHOD(_placeholder_destructor)(THIS) PURE;
    STDMETHOD(_OldInit)(THIS) PURE;
    STDMETHOD(CheckHaveMatch)(THIS_ BSTR szName, VARIANT_BOOL FAR* retVal) PURE;
    STDMETHOD(Init)(THIS_ SysKinds SysKind, long LCID, short GrowSize) PURE;
};

DEFINE_GUID(CLSID_SearchHelper,0x8B217752L,0x717D,0x11CE,0xAB,0x5B,0xD4,0x12,0x03,0xC1,0x00,0x00);
class CSearchHelper
{
public:
    CSearchHelper()
    {
      m_pInternal = NULL;
      IUnknown FAR* pUnk;
      if SUCCEEDED(m_hrLaunch = CoCreateInstance(CLSID_SearchHelper, NULL, CLSCTX_SERVER,
                                               IID_IUnknown, (void FAR* FAR*) &pUnk)) {
        m_hrLaunch = pUnk->QueryInterface(IID__SearchHelper, (void FAR* FAR*) &m_pInternal);
        pUnk->Release();
      }
    }
    virtual ~CSearchHelper(){if (m_pInternal) m_pInternal->Release();}
    HRESULT LaunchError(){return m_hrLaunch;}
    inline _SearchHelper* operator->(){return m_pInternal;}
private:
    _SearchHelper FAR* m_pInternal;
    HRESULT m_hrLaunch;
};

DEFINE_GUID(IID_SearchItem,0x8B217756L,0x717D,0x11CE,0xAB,0x5B,0xD4,0x12,0x03,0xC1,0x00,0x00);
DECLARE_INTERFACE_(SearchItem, IDispatch)
{
    STDMETHOD(Me)(THIS_ SearchItem FAR* FAR* retVal) PURE;
    STDMETHOD(_placeholder_destructor)(THIS) PURE;
    STDMETHOD(get_Name)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get_SearchData)(THIS_ long FAR* retVal) PURE;
    STDMETHOD(get_TypeInfoNumber)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get__OldLibNum)(THIS_ unsigned char FAR* retVal) PURE;
    STDMETHOD(get_SearchType)(THIS_ TliSearchTypes FAR* retVal) PURE;
    STDMETHOD(get_MemberId)(THIS_ long FAR* retVal) PURE;
    STDMETHOD(get_InvokeKinds)(THIS_ InvokeKinds FAR* retVal) PURE;
    STDMETHOD(get_NamePtrW)(THIS_ long FAR* retVal) PURE;
    STDMETHOD(get_LibNum)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_Constant)(THIS_ VARIANT_BOOL FAR* retVal) PURE;
    STDMETHOD(get_Hidden)(THIS_ VARIANT_BOOL FAR* retVal) PURE;
    STDMETHOD(get_InvokeGroup)(THIS_ short FAR* retVal) PURE;
};

DEFINE_GUID(IID_SearchResults,0x8B217757L,0x717D,0x11CE,0xAB,0x5B,0xD4,0x12,0x03,0xC1,0x00,0x00);
DECLARE_INTERFACE_(SearchResults, IDispatch)
{
    STDMETHOD(Me)(THIS_ SearchResults FAR* FAR* retVal) PURE;
    STDMETHOD(_placeholder_destructor)(THIS) PURE;
    STDMETHOD(_NewEnum)(THIS_ LPUNKNOWN FAR* retVal) PURE;
    STDMETHOD(get__OldItem)(THIS_ short Index, SearchItem FAR* FAR* retVal) PURE;
    STDMETHOD(get__OldCount)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_Sorted)(THIS_ VARIANT_BOOL FAR* retVal) PURE;
    STDMETHOD(Sort)(THIS_ CustomSort FAR* CustomSort) PURE;
    STDMETHOD(Filter)(THIS_ CustomFilter FAR* CustomFilter, SearchResults FAR* FAR* AppendExtractedTo, SearchItem FAR* StartAfter, SearchResults FAR* FAR* retVal) PURE;
    STDMETHOD(get_Item)(THIS_ long Index, SearchItem FAR* FAR* retVal) PURE;
    STDMETHOD(get_Count)(THIS_ long FAR* retVal) PURE;
    STDMETHOD(LocateSorted)(THIS_ CustomSort FAR* CustomSort, long FAR* retVal) PURE;
    STDMETHOD(Locate)(THIS_ BSTR SearchString, CustomSort FAR* CustomSort, long StartAfter, long FAR* retVal) PURE;
};

DEFINE_GUID(IID__TLIApplication,0x8B21775DL,0x717D,0x11CE,0xAB,0x5B,0xD4,0x12,0x03,0xC1,0x00,0x00);
DECLARE_INTERFACE_(_TLIApplication, IDispatch)
{
    STDMETHOD(Me)(THIS_ TLIApplication FAR* FAR* retVal) PURE;
    STDMETHOD(_placeholder_destructor)(THIS) PURE;
    STDMETHOD(TypeLibInfoFromFile)(THIS_ BSTR FileName, TypeLibInfo FAR* FAR* retVal) PURE;
    STDMETHOD(InterfaceInfoFromObject)(THIS_ LPDISPATCH Object, InterfaceInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_ListBoxNotification)(THIS_ ListBoxNotification FAR* FAR* retVal) PURE;
    STDMETHOD(putref_ListBoxNotification)(THIS_ ListBoxNotification FAR* retVal) PURE;
    STDMETHOD(get_ResolveAliases)(THIS_ VARIANT_BOOL FAR* retVal) PURE;
    STDMETHOD(put_ResolveAliases)(THIS_ VARIANT_BOOL retVal) PURE;
    STDMETHOD(InvokeHook)(THIS_ LPDISPATCH Object, VARIANT ID, InvokeKinds InvokeKind, LPSAFEARRAY FAR* ReverseArgList, VARIANT FAR* retVal) PURE;
    STDMETHOD(InvokeHookArray)(THIS_ LPDISPATCH Object, VARIANT ID, InvokeKinds InvokeKind, LPSAFEARRAY FAR* ReverseArgList, VARIANT FAR* retVal) PURE;
    STDMETHOD(InvokeHookSub)(THIS_ LPDISPATCH Object, VARIANT ID, InvokeKinds InvokeKind, LPSAFEARRAY FAR* ReverseArgList) PURE;
    STDMETHOD(InvokeHookArraySub)(THIS_ LPDISPATCH Object, VARIANT ID, InvokeKinds InvokeKind, LPSAFEARRAY FAR* ReverseArgList) PURE;
    STDMETHOD(ClassInfoFromObject)(THIS_ LPUNKNOWN Object, TypeInfo FAR* FAR* retVal) PURE;
    STDMETHOD(InvokeID)(THIS_ LPDISPATCH Object, BSTR Name, long FAR* retVal) PURE;
    STDMETHOD(get_InvokeLCID)(THIS_ long FAR* retVal) PURE;
    STDMETHOD(put_InvokeLCID)(THIS_ long retVal) PURE;
    STDMETHOD(TypeInfoFromITypeInfo)(THIS_ LPUNKNOWN ptinfo, TypeInfo FAR* FAR* retVal) PURE;
    STDMETHOD(TypeLibInfoFromITypeLib)(THIS_ IUnknown * pITypeLib, TypeLibInfo FAR* FAR* retVal) PURE;
    STDMETHOD(TypeLibInfoFromRegistry)(THIS_ BSTR TypeLibGuid, short MajorVersion, short MinorVersion, long LCID, TypeLibInfo FAR* FAR* retVal) PURE;
    STDMETHOD(TypeInfoFromRecordVariant)(THIS_ VARIANT FAR* RecordVariant, TypeInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_RecordField)(THIS_ VARIANT FAR* RecordVariant, BSTR FAR* FieldName, VARIANT FAR* retVal) PURE;
    STDMETHOD(put_RecordField)(THIS_ VARIANT FAR* RecordVariant, BSTR FAR* FieldName, VARIANT FAR* NewValue) PURE;
    STDMETHOD(putref_RecordField)(THIS_ VARIANT FAR* RecordVariant, BSTR FAR* FieldName, VARIANT FAR* NewValue) PURE;
};

DEFINE_GUID(CLSID_TLIApplication,0x8B21775EL,0x717D,0x11CE,0xAB,0x5B,0xD4,0x12,0x03,0xC1,0x00,0x00);
class CTLIApplication
{
public:
    CTLIApplication()
    {
      m_pInternal = NULL;
      IUnknown FAR* pUnk;
      if SUCCEEDED(m_hrLaunch = CoCreateInstance(CLSID_TLIApplication, NULL, CLSCTX_SERVER,
                                               IID_IUnknown, (void FAR* FAR*) &pUnk)) {
        m_hrLaunch = pUnk->QueryInterface(IID__TLIApplication, (void FAR* FAR*) &m_pInternal);
        pUnk->Release();
      }
    }
    virtual ~CTLIApplication(){if (m_pInternal) m_pInternal->Release();}
    HRESULT LaunchError(){return m_hrLaunch;}
    inline _TLIApplication* operator->(){return m_pInternal;}
private:
    _TLIApplication FAR* m_pInternal;
    HRESULT m_hrLaunch;
};

DEFINE_GUID(IID_TypeInfo,0x8B217759L,0x717D,0x11CE,0xAB,0x5B,0xD4,0x12,0x03,0xC1,0x00,0x00);
DECLARE_INTERFACE_(TypeInfo, IDispatch)
{
    STDMETHOD(Me)(THIS_ TypeInfo FAR* FAR* retVal) PURE;
    STDMETHOD(_placeholder_destructor)(THIS) PURE;
    STDMETHOD(get_Name)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get_GUID)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get__OldHelpString)(THIS) PURE;
    STDMETHOD(get_HelpContext)(THIS_ long FAR* retVal) PURE;
    STDMETHOD(get_HelpFile)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get_AttributeMask)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_AttributeStrings)(THIS_ LPSAFEARRAY FAR* AttributeArray, short FAR* retVal) PURE;
    STDMETHOD(get__OldTypeKind)(THIS) PURE;
    STDMETHOD(get_TypeKindString)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get_TypeInfoNumber)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_VTableInterface)(THIS_ InterfaceInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_GetMember)(THIS_ VARIANT Index, MemberInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_Members)(THIS_ Members FAR* FAR* retVal) PURE;
    STDMETHOD(get_Parent)(THIS_ TypeLibInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_Interfaces)(THIS_ Interfaces FAR* FAR* retVal) PURE;
    STDMETHOD(get_DefaultInterface)(THIS_ InterfaceInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_DefaultEventInterface)(THIS_ InterfaceInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_TypeKind)(THIS_ TypeKinds FAR* retVal) PURE;
    STDMETHOD(get_ResolvedType)(THIS_ VarTypeInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_CustomDataCollection)(THIS_ CustomDataCollection FAR* FAR* retVal) PURE;
    STDMETHOD(get_HelpString)(THIS_ long LCID, BSTR FAR* retVal) PURE;
    STDMETHOD(get_ITypeInfo)(THIS_ LPUNKNOWN FAR* retVal) PURE;
    STDMETHOD(get_MajorVersion)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_MinorVersion)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_HelpStringDll)(THIS_ long LCID, BSTR FAR* retVal) PURE;
    STDMETHOD(get_HelpStringContext)(THIS_ long FAR* retVal) PURE;
};

DEFINE_GUID(IID_TypeInfos,0x8B21775AL,0x717D,0x11CE,0xAB,0x5B,0xD4,0x12,0x03,0xC1,0x00,0x00);
DECLARE_INTERFACE_(TypeInfos, IDispatch)
{
    STDMETHOD(Me)(THIS_ TypeInfos FAR* FAR* retVal) PURE;
    STDMETHOD(_placeholder_destructor)(THIS) PURE;
    STDMETHOD(_NewEnum)(THIS_ LPUNKNOWN FAR* retVal) PURE;
    STDMETHOD(get_Count)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_Item)(THIS_ short Index, TypeInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_IndexedItem)(THIS_ short TypeInfoNumber, TypeInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_NamedItem)(THIS_ BSTR FAR* TypeInfoName, TypeInfo FAR* FAR* retVal) PURE;
};

DEFINE_GUID(IID__TypeLibInfo,0x8B217745L,0x717D,0x11CE,0xAB,0x5B,0xD4,0x12,0x03,0xC1,0x00,0x00);
DECLARE_INTERFACE_(_TypeLibInfo, IDispatch)
{
    STDMETHOD(Me)(THIS_ TypeLibInfo FAR* FAR* retVal) PURE;
    STDMETHOD(_placeholder_destructor)(THIS) PURE;
    STDMETHOD(get_ContainingFile)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(put_ContainingFile)(THIS_ BSTR retVal) PURE;
    STDMETHOD(LoadRegTypeLib)(THIS_ BSTR TypeLibGuid, short MajorVersion, short MinorVersion, long LCID) PURE;
    STDMETHOD(get_Name)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get__OldHelpString)(THIS) PURE;
    STDMETHOD(get_HelpContext)(THIS_ long FAR* retVal) PURE;
    STDMETHOD(get_HelpFile)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get_GUID)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get_LCID)(THIS_ long FAR* retVal) PURE;
    STDMETHOD(get__OldSysKind)(THIS) PURE;
    STDMETHOD(get_MajorVersion)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_MinorVersion)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_AttributeMask)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_AttributeStrings)(THIS_ LPSAFEARRAY FAR* AttributeArray, short FAR* retVal) PURE;
    STDMETHOD(get_CoClasses)(THIS_ CoClasses FAR* FAR* retVal) PURE;
    STDMETHOD(get_Interfaces)(THIS_ Interfaces FAR* FAR* retVal) PURE;
    STDMETHOD(get_Constants)(THIS_ Constants FAR* FAR* retVal) PURE;
    STDMETHOD(get_Declarations)(THIS_ Declarations FAR* FAR* retVal) PURE;
    STDMETHOD(get_TypeInfoCount)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get__OldGetTypeKind)(THIS) PURE;
    STDMETHOD(get_GetTypeInfo)(THIS_ VARIANT FAR* Index, TypeInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_GetTypeInfoNumber)(THIS_ BSTR Name, short FAR* retVal) PURE;
    STDMETHOD(IsSameLibrary)(THIS_ TypeLibInfo FAR* CheckLib, VARIANT_BOOL FAR* retVal) PURE;
    STDMETHOD(_OldResetSearchCriteria)(THIS) PURE;
    STDMETHOD(_OldGetTypesWithMember)(THIS) PURE;
    STDMETHOD(_OldGetMembersWithSubString)(THIS) PURE;
    STDMETHOD(_OldGetTypesWithSubString)(THIS) PURE;
    STDMETHOD(_OldCaseTypeName)(THIS) PURE;
    STDMETHOD(_OldCaseMemberName)(THIS) PURE;
    STDMETHOD(_OldFillTypesList)(THIS) PURE;
    STDMETHOD(_OldFillTypesCombo)(THIS) PURE;
    STDMETHOD(_OldFillMemberList)(THIS) PURE;
    STDMETHOD(_OldAddClassTypeToList)(THIS) PURE;
    STDMETHOD(put_AppObjString)(THIS_ BSTR retVal) PURE;
    STDMETHOD(put_LibNum)(THIS_ short retVal) PURE;
    STDMETHOD(get_ShowLibName)(THIS_ VARIANT_BOOL FAR* retVal) PURE;
    STDMETHOD(put_ShowLibName)(THIS_ VARIANT_BOOL retVal) PURE;
    STDMETHOD(putref__OldListBoxNotification)(THIS_ ListBoxNotification FAR* Param1) PURE;
    STDMETHOD(get_GetTypeKind)(THIS_ short TypeInfoNumber, TypeKinds FAR* retVal) PURE;
    STDMETHOD(get_SysKind)(THIS_ SysKinds FAR* retVal) PURE;
    STDMETHOD(get_SearchDefault)(THIS_ TliSearchTypes FAR* retVal) PURE;
    STDMETHOD(put_SearchDefault)(THIS_ TliSearchTypes retVal) PURE;
    STDMETHOD(CaseTypeName)(THIS_ BSTR FAR* bstrName, TliSearchTypes SearchType, TliSearchTypes FAR* retVal) PURE;
    STDMETHOD(CaseMemberName)(THIS_ BSTR FAR* bstrName, TliSearchTypes SearchType, VARIANT_BOOL FAR* retVal) PURE;
    STDMETHOD(ResetSearchCriteria)(THIS_ TypeFlags TypeFilter, VARIANT_BOOL IncludeEmptyTypes, VARIANT_BOOL ShowUnderscore) PURE;
    STDMETHOD(GetTypesWithMember)(THIS_ BSTR MemberName, SearchResults FAR* FAR* StartResults, TliSearchTypes SearchType, VARIANT_BOOL Sort, VARIANT_BOOL ShowUnderscore,
        SearchResults FAR* FAR* retVal) PURE;
    STDMETHOD(GetTypesWithMemberDirect)(THIS_ BSTR MemberName, int hWnd, TliWindowTypes WindowType, TliSearchTypes SearchType, VARIANT_BOOL ShowUnderscore, short FAR*
        retVal) PURE;
    STDMETHOD(GetMembersWithSubString)(THIS_ BSTR SubString, SearchResults FAR* FAR* StartResults, TliSearchTypes SearchType, VARIANT_BOOL SearchMiddle, SearchHelper
        FAR* FAR* Helper, VARIANT_BOOL Sort, VARIANT_BOOL ShowUnderscore, SearchResults FAR* FAR* retVal) PURE;
    STDMETHOD(GetMembersWithSubStringDirect)(THIS_ BSTR SubString, int hWnd, TliWindowTypes WindowType, TliSearchTypes SearchType, VARIANT_BOOL SearchMiddle, SearchHelper
        FAR* FAR* Helper, VARIANT_BOOL ShowUnderscore, short FAR* retVal) PURE;
    STDMETHOD(GetTypesWithSubString)(THIS_ BSTR SubString, SearchResults FAR* FAR* StartResults, TliSearchTypes SearchType, VARIANT_BOOL SearchMiddle, VARIANT_BOOL Sort,
        SearchResults FAR* FAR* retVal) PURE;
    STDMETHOD(GetTypesWithSubStringDirect)(THIS_ BSTR SubString, int hWnd, TliWindowTypes WindowType, TliSearchTypes SearchType, VARIANT_BOOL SearchMiddle, short FAR*
        retVal) PURE;
    STDMETHOD(GetTypes)(THIS_ SearchResults FAR* FAR* StartResults, TliSearchTypes SearchType, VARIANT_BOOL Sort, SearchResults FAR* FAR* retVal) PURE;
    STDMETHOD(GetTypesDirect)(THIS_ int hWnd, TliWindowTypes WindowType, TliSearchTypes SearchType, short FAR* retVal) PURE;
    STDMETHOD(GetMembers)(THIS_ long SearchData, VARIANT_BOOL ShowUnderscore, SearchResults FAR* FAR* retVal) PURE;
    STDMETHOD(GetMembersDirect)(THIS_ long SearchData, int hWnd, TliWindowTypes WindowType, TliItemDataTypes ItemDataType, VARIANT_BOOL ShowUnderscore, short FAR* retVal) PURE;
    STDMETHOD(SetMemberFilters)(THIS_ FuncFlags FuncFilter, VarFlags VarFilter) PURE;
    STDMETHOD(MakeSearchData)(THIS_ BSTR TypeInfoName, TliSearchTypes SearchType, long FAR* retVal) PURE;
    STDMETHOD(get_TypeInfos)(THIS_ TypeInfos FAR* FAR* retVal) PURE;
    STDMETHOD(get_Records)(THIS_ Records FAR* FAR* retVal) PURE;
    STDMETHOD(get_IntrinsicAliases)(THIS_ IntrinsicAliases FAR* FAR* retVal) PURE;
    STDMETHOD(get_CustomDataCollection)(THIS_ CustomDataCollection FAR* FAR* retVal) PURE;
    STDMETHOD(GetMemberInfo)(THIS_ long SearchData, InvokeKinds InvokeKinds, long MemberId, BSTR MemberName, MemberInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_Unions)(THIS_ Unions FAR* FAR* retVal) PURE;
    STDMETHOD(AddTypes)(THIS_ LPSAFEARRAY FAR* TypeInfoNumbers, SearchResults FAR* FAR* StartResults, TliSearchTypes SearchType, VARIANT_BOOL Sort, SearchResults FAR*
        FAR* retVal) PURE;
    STDMETHOD(AddTypesDirect)(THIS_ LPSAFEARRAY FAR* TypeInfoNumbers, int hWnd, TliWindowTypes WindowType, TliSearchTypes SearchType, short FAR* retVal) PURE;
    STDMETHOD(FreeSearchCriteria)(THIS) PURE;
    STDMETHOD(Register)(THIS_ BSTR HelpDir) PURE;
    STDMETHOD(UnRegister)(THIS) PURE;
    STDMETHOD(get_HelpString)(THIS_ long LCID, BSTR FAR* retVal) PURE;
    STDMETHOD(get_AppObjString)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get_LibNum)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(GetMembersWithSubStringEx)(THIS_ BSTR SubString, LPSAFEARRAY FAR* InvokeGroupings, SearchResults FAR* FAR* StartResults, TliSearchTypes SearchType, VARIANT_BOOL
        SearchMiddle, VARIANT_BOOL Sort, VARIANT_BOOL ShowUnderscore, SearchResults FAR* FAR* retVal) PURE;
    STDMETHOD(GetTypesWithMemberEx)(THIS_ BSTR MemberName, InvokeKinds InvokeKind, SearchResults FAR* FAR* StartResults, TliSearchTypes SearchType, VARIANT_BOOL Sort,
        VARIANT_BOOL ShowUnderscore, SearchResults FAR* FAR* retVal) PURE;
    STDMETHOD(get_ITypeLib)(THIS_ LPUNKNOWN FAR* retVal) PURE;
    STDMETHOD(putref_ITypeLib)(THIS_ LPUNKNOWN retVal) PURE;
    STDMETHOD(get_HelpStringDll)(THIS_ long LCID, BSTR FAR* retVal) PURE;
    STDMETHOD(get_HelpStringContext)(THIS_ long FAR* retVal) PURE;
    STDMETHOD(get_BestEquivalentType)(THIS_ BSTR TypeInfoName, BSTR FAR* retVal) PURE;
};

DEFINE_GUID(CLSID_TypeLibInfo,0x8B217746L,0x717D,0x11CE,0xAB,0x5B,0xD4,0x12,0x03,0xC1,0x00,0x00);
class CTypeLibInfo
{
public:
    CTypeLibInfo()
    {
      m_pInternal = NULL;
      IUnknown FAR* pUnk;
      if SUCCEEDED(m_hrLaunch = CoCreateInstance(CLSID_TypeLibInfo, NULL, CLSCTX_SERVER,
                                               IID_IUnknown, (void FAR* FAR*) &pUnk)) {
        m_hrLaunch = pUnk->QueryInterface(IID__TypeLibInfo, (void FAR* FAR*) &m_pInternal);
        pUnk->Release();
      }
    }
    virtual ~CTypeLibInfo(){if (m_pInternal) m_pInternal->Release();}
    HRESULT LaunchError(){return m_hrLaunch;}
    inline _TypeLibInfo* operator->(){return m_pInternal;}
private:
    _TypeLibInfo FAR* m_pInternal;
    HRESULT m_hrLaunch;
};

DEFINE_GUID(IID_UnionInfo,0x8B217765L,0x717D,0x11CE,0xAB,0x5B,0xD4,0x12,0x03,0xC1,0x00,0x00);
DECLARE_INTERFACE_(UnionInfo, IDispatch)
{
    STDMETHOD(Me)(THIS_ TypeInfo FAR* FAR* retVal) PURE;
    STDMETHOD(_placeholder_destructor)(THIS) PURE;
    STDMETHOD(get_Name)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get_GUID)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get__OldHelpString)(THIS) PURE;
    STDMETHOD(get_HelpContext)(THIS_ long FAR* retVal) PURE;
    STDMETHOD(get_HelpFile)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get_AttributeMask)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_AttributeStrings)(THIS_ LPSAFEARRAY FAR* AttributeArray, short FAR* retVal) PURE;
    STDMETHOD(get__OldTypeKind)(THIS) PURE;
    STDMETHOD(get_TypeKindString)(THIS_ BSTR FAR* retVal) PURE;
    STDMETHOD(get_TypeInfoNumber)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(_placeholder_VTableInterface)(THIS) PURE;
    STDMETHOD(get_GetMember)(THIS_ VARIANT Index, MemberInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_Members)(THIS_ Members FAR* FAR* retVal) PURE;
    STDMETHOD(get_Parent)(THIS_ TypeLibInfo FAR* FAR* retVal) PURE;
    STDMETHOD(_ImpliedInterfaces)(THIS) PURE;
    STDMETHOD(_DefaultInterface)(THIS) PURE;
    STDMETHOD(_DefaultEventInterface)(THIS) PURE;
    STDMETHOD(get_TypeKind)(THIS_ TypeKinds FAR* retVal) PURE;
    STDMETHOD(get_ResolvedType)(THIS_ VarTypeInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_CustomDataCollection)(THIS_ CustomDataCollection FAR* FAR* retVal) PURE;
    STDMETHOD(get_HelpString)(THIS_ long LCID, BSTR FAR* retVal) PURE;
    STDMETHOD(get_ITypeInfo)(THIS_ LPUNKNOWN FAR* retVal) PURE;
    STDMETHOD(get_MajorVersion)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_MinorVersion)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_HelpStringDll)(THIS_ long LCID, BSTR FAR* retVal) PURE;
    STDMETHOD(get_HelpStringContext)(THIS_ long FAR* retVal) PURE;
};

DEFINE_GUID(IID_Unions,0x8B217766L,0x717D,0x11CE,0xAB,0x5B,0xD4,0x12,0x03,0xC1,0x00,0x00);
DECLARE_INTERFACE_(Unions, IDispatch)
{
    STDMETHOD(Me)(THIS_ TypeInfos FAR* FAR* retVal) PURE;
    STDMETHOD(_placeholder_destructor)(THIS) PURE;
    STDMETHOD(_NewEnum)(THIS_ LPUNKNOWN FAR* retVal) PURE;
    STDMETHOD(get_Count)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_Item)(THIS_ short Index, UnionInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_IndexedItem)(THIS_ short TypeInfoNumber, UnionInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_NamedItem)(THIS_ BSTR FAR* TypeInfoName, UnionInfo FAR* FAR* retVal) PURE;
};

DEFINE_GUID(IID_VarTypeInfo,0x8B21774BL,0x717D,0x11CE,0xAB,0x5B,0xD4,0x12,0x03,0xC1,0x00,0x00);
DECLARE_INTERFACE_(VarTypeInfo, IDispatch)
{
    STDMETHOD(Me)(THIS_ VarTypeInfo FAR* FAR* retVal) PURE;
    STDMETHOD(_placeholder_destructor)(THIS) PURE;
    STDMETHOD(get__OldVarType)(THIS) PURE;
    STDMETHOD(get_TypeInfo)(THIS_ TypeInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_TypeInfoNumber)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_TypedVariant)(THIS_ VARIANT FAR* retVal) PURE;
    STDMETHOD(get_IsExternalType)(THIS_ VARIANT_BOOL FAR* retVal) PURE;
    STDMETHOD(get_TypeLibInfoExternal)(THIS_ TypeLibInfo FAR* FAR* retVal) PURE;
    STDMETHOD(get_PointerLevel)(THIS_ short FAR* retVal) PURE;
    STDMETHOD(get_VarType)(THIS_ TliVarType FAR* retVal) PURE;
    STDMETHOD(ArrayBounds)(THIS_ LPSAFEARRAY FAR* Bounds, short FAR* retVal) PURE;
    STDMETHOD(get_ElementPointerLevel)(THIS_ short FAR* retVal) PURE;
};
#endif //_TLBINF_H_