'\ This VBA project browses typelibs at runtime via low level vTable calls.
'\ Requiremets:
'\ ===========
' - This project requires a reference to Visual Basic for Applications Extensibility.
' - 'Trust access to Visual Basic Project' must also be set.
Option Explicit
Public Enum SEARCH_TARGET
Class_
Interface_
Module_
Enum_
End Enum
Private Const TKIND_ENUM = 0&
Public Enum TKIND
EI = TKIND_ENUM
MI = TKIND_ENUM + 2& 'TKIND_MODULE
II = TKIND_ENUM + 3& 'TKIND_INTERFACE
CI = TKIND_ENUM + 5& 'TKIND_COCLASS
DI = TKIND_ENUM + 4& 'TKIND_DISPATCH
End Enum
Public Enum IMPLTYPEFLAGS
IMPLTYPEFLAG_FDEFAULT = 1&
IMPLTYPEFLAG_FSOURCE = 2&
IMPLTYPEFLAG_FRESTRICTED = 4&
IMPLTYPEFLAG_FDEFAULTVTABLE = 8&
End Enum
Private Enum VarEnum
VT_EMPTY = 0&
VT_NULL = 1&
VT_I2 = 2&
VT_I4 = 3&
VT_R4 = 4&
VT_R8 = 5&
VT_CY = 6&
VT_DATE = 7&
VT_BSTR = 8&
VT_DISPATCH = 9&
VT_ERROR = 10&
VT_BOOL = 11&
VT_VARIANT = 12&
VT_UNKNOWN = 13&
VT_DECIMAL = 14&
VT_I1 = 16&
VT_UI1 = 17&
VT_UI2 = 18&
VT_UI4 = 19&
VT_I8 = 20&
VT_UI8 = 21&
VT_INT = 22&
VT_UINT = 23&
VT_VOID = 24&
VT_HRESULT = 25&
VT_PTR = 26&
VT_SAFEARRAY = 27&
VT_CARRAY = 28&
VT_USERDEFINED = 29&
VT_LPSTR = 30&
VT_LPWSTR = 31&
VT_RECORD = 36&
VT_FILETIME = 64&
VT_BLOB = 65&
VT_STREAM = 66&
VT_STORAGE = 67&
VT_STREAMED_OBJECT = 68&
VT_STORED_OBJECT = 69&
VT_BLOB_OBJECT = 70&
VT_CF = 71&
VT_CLSID = 72&
VT_BSTR_BLOB = &HFFF&
VT_VECTOR = &H1000&
VT_ARRAY = &H2000&
VT_BYREF = &H4000&
VT_RESERVED = &H8000&
VT_ILLEGAL = &HFFFF&
End Enum
#If Win64 Then
Private Const NULL_PTR = 0^
Private Const PTR_LEN = 8&
#Else
Private Const NULL_PTR = 0&
Private Const PTR_LEN = 4&
#End If
#If VBA7 Then
Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
Private Declare PtrSafe Function SysReAllocString Lib "oleaut32.dll" (ByVal pBSTR As LongPtr, Optional ByVal pszStrPtr As LongPtr) As Long
Private Declare PtrSafe Sub CoTaskMemFree Lib "ole32.dll" (ByVal PV As LongPtr)
Private Declare PtrSafe Function DispCallFunc Lib "oleaut32.dll" (ByVal pvInstance As LongPtr, ByVal offsetinVft As LongPtr, ByVal CallConv As Long, ByVal retTYP As Integer, ByVal paCNT As Long, ByRef paTypes As Integer, ByRef paValues As LongPtr, ByRef retVAR As Variant) As Long
Private Declare PtrSafe Sub SetLastError Lib "kernel32.dll" (ByVal dwErrCode As Long)
Private Declare PtrSafe Function StringFromIID Lib "ole32" (ByRef lpsz As GUID, ByVal rclsid As LongPtr) As Long
Private Declare PtrSafe Function LoadTypeLibEx Lib "OleAut32" (ByVal szFile As LongPtr, ByVal regkind As Long, ByRef pptlib As IUnknown) As Long
Private Declare PtrSafe Function GetCurrentProcess Lib "kernel32" () As LongPtr
Private Declare PtrSafe Function CloseHandle Lib "kernel32.dll" (ByVal hObject As LongPtr) As Long
Private Declare PtrSafe Function GetModuleInformation Lib "psapi.dll" (ByVal hProcess As LongPtr, ByVal hModule As LongPtr, mInfo As MODULEINFO, ByVal cbSize As Long) As Long
Private Declare PtrSafe Function GetModuleFileNameExW Lib "psapi.dll" (ByVal hProcess As LongPtr, ByVal hModule As LongPtr, ByVal lpFileName As LongPtr, ByVal nSize As Long) As Long
Private Declare PtrSafe Function EnumProcessModules Lib "psapi.dll" (ByVal hProcess As LongPtr, lphModule As LongPtr, ByVal cb As Long, lpcbNeeded As Long) As Long
Private Declare PtrSafe Function GetModuleBaseNameW Lib "psapi.dll" (ByVal hProcess As LongPtr, ByVal hModule As LongPtr, ByVal lpFileName As LongPtr, ByVal nSize As Long) As Long
Private Declare PtrSafe Function GetModuleFileNameW Lib "kernel32" (ByVal hModule As LongPtr, ByVal lpFileName As LongPtr, ByVal nSize As Long) As Long
Private Declare PtrSafe Function GetModuleHandleW Lib "kernel32" (ByVal lpModuleName As LongPtr) As LongPtr
Private Declare PtrSafe Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As LongPtr
Private Declare PtrSafe Function GetModuleFileName Lib "kernel32" Alias "GetModuleFileNameA" (ByVal hModule As LongPtr, ByVal lpFileName As String, ByVal nSize As Long) As Long
Private Declare PtrSafe Function GetClientRect Lib "user32" (ByVal hwnd As LongPtr, lpRect As RECT) As Long
Private Declare PtrSafe Function GetDC Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
Private Declare PtrSafe Function ReleaseDC Lib "user32" (ByVal hwnd As LongPtr, ByVal hDC As LongPtr) As Long
Private Declare PtrSafe Function SelectObject Lib "gdi32" (ByVal hDC As LongPtr, ByVal hObject As LongPtr) As LongPtr
Private Declare PtrSafe Function GetTextExtentPoint32 Lib "gdi32" Alias "GetTextExtentPoint32A" (ByVal hDC As LongPtr, ByVal lpsz As String, ByVal cbString As Long, lpSize As Size) As Long
Private Declare PtrSafe Function InvalidateRect Lib "user32" (ByVal hwnd As LongPtr, lpRect As Any, ByVal bErase As Long) As Long
Private Declare PtrSafe Function SetBkMode Lib "gdi32" (ByVal hDC As LongPtr, ByVal nBkMode As Long) As Long
Private Declare PtrSafe Function SetRect Lib "user32" (lpRect As RECT, ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long
Private Declare PtrSafe Function DrawText Lib "user32" Alias "DrawTextW" (ByVal hDC As LongPtr, ByVal lpStr As LongPtr, ByVal nCount As Long, lpRect As RECT, ByVal wFormat As Long) As Long
Private Declare PtrSafe Function SetTextColor Lib "gdi32" (ByVal hDC As LongPtr, ByVal crColor As Long) As Long
Private Declare PtrSafe Function SetTimer Lib "user32" (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr, ByVal uElapse As Long, ByVal lpTimerFunc As LongPtr) As LongPtr
Private Declare PtrSafe Function KillTimer Lib "user32" (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr) As Long
Private Declare PtrSafe Function IUnknown_GetWindow Lib "shlwapi" Alias "#172" (ByVal pIUnk As IUnknown, ByVal hUF As LongPtr) As Long
#Else
Private Enum LongPtr
[_]
End Enum
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
Private Declare Function SysReAllocString Lib "oleaut32.dll" (ByVal pBSTR As LongPtr, Optional ByVal pszStrPtr As LongPtr) As Long
Private Declare Sub CoTaskMemFree Lib "ole32.dll" (ByVal PV As LongPtr)
Private Declare Function DispCallFunc Lib "oleaut32.dll" (ByVal pvInstance As LongPtr, ByVal offsetinVft As LongPtr, ByVal CallConv As Long, ByVal retTYP As Integer, ByVal paCNT As Long, ByRef paTypes As Integer, ByRef paValues As LongPtr, ByRef retVAR As Variant) As Long
Private Declare Sub SetLastError Lib "kernel32.dll" (ByVal dwErrCode As Long)
Private Declare Function StringFromIID Lib "ole32" (ByRef lpsz As GUID, ByVal rclsid As LongPtr) As Long
Private Declare Function LoadTypeLibEx Lib "OleAut32" (ByVal szFile As LongPtr, ByVal regkind As Long, ByRef pptlib As IUnknown) As Long
Private Declare Function GetCurrentProcess Lib "kernel32" () As LongPtr
Private Declare Function CloseHandle Lib "kernel32.dll" (ByVal hObject As LongPtr) As Long
Private Declare Function GetModuleInformation Lib "psapi.dll" (ByVal hProcess As LongPtr, ByVal hModule As LongPtr, mInfo As MODULEINFO, ByVal cbSize As Long) As Long
Private Declare Function GetModuleFileNameExW Lib "psapi.dll" (ByVal hProcess As LongPtr, ByVal hModule As LongPtr, ByVal lpFileName As LongPtr, ByVal nSize As Long) As Long
Private Declare Function EnumProcessModules Lib "psapi.dll" (ByVal hProcess As LongPtr, lphModule As LongPtr, ByVal cb As Long, lpcbNeeded As Long) As Long
Private Declare Function GetModuleBaseNameW Lib "psapi.dll" (ByVal hProcess As LongPtr, ByVal hModule As LongPtr, ByVal lpFileName As LongPtr, ByVal nSize As Long) As Long
Private Declare Function GetModuleFileNameW Lib "kernel32" (ByVal hModule As LongPtr, ByVal lpFileName As LongPtr, ByVal nSize As Long) As Long
Private Declare Function GetModuleHandleW Lib "kernel32" (ByVal lpModuleName As LongPtr) As LongPtr
Private Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As LongPtr
Private Declare Function GetModuleFileName Lib "kernel32" Alias "GetModuleFileNameA" (ByVal hModule As LongPtr, ByVal lpFileName As String, ByVal nSize As Long) As Long
Private Declare Function GetClientRect Lib "user32" (ByVal hwnd As LongPtr, lpRect As RECT) As Long
Private Declare Function GetDC Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As LongPtr, ByVal hDC As LongPtr) As Long
Private Declare Function SelectObject Lib "gdi32" (ByVal hDC As LongPtr, ByVal hObject As LongPtr) As LongPtr
Private Declare Function GetTextExtentPoint32 Lib "gdi32" Alias "GetTextExtentPoint32A" (ByVal hDC As LongPtr, ByVal lpsz As String, ByVal cbString As Long, lpSize As Size) As Long
Private Declare Function InvalidateRect Lib "user32" (ByVal hwnd As LongPtr, lpRect As Any, ByVal bErase As Long) As Long
Private Declare Function SetBkMode Lib "gdi32" (ByVal hDC As LongPtr, ByVal nBkMode As Long) As Long
Private Declare Function SetRect Lib "user32" (lpRect As RECT, ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long
Private Declare Function DrawText Lib "user32" Alias "DrawTextW" (ByVal hDC As LongPtr, ByVal lpStr As LongPtr, ByVal nCount As Long, lpRect As RECT, ByVal wFormat As Long) As Long
Private Declare Function SetTextColor Lib "gdi32" (ByVal hDC As LongPtr, ByVal crColor As Long) As Long
Private Declare Function SetTimer Lib "user32" (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr, ByVal uElapse As Long, ByVal lpTimerFunc As LongPtr) As LongPtr
Private Declare Function KillTimer Lib "user32" (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr) As Long
Private Declare Function IUnknown_GetWindow Lib "shlwapi" Alias "#172" (ByVal pIUnk As IUnknown, ByVal hUF As LongPtr) As Long
#End If
Private Type Size
cx As Long
cy As Long
End Type
Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Public Type FUNC_INFO
Name As String
memid As Long
CallConvention As Long
funckind As Long
VTBLOffset As Long
INVOKEKIND As String
ParamsCount As Long
OptParamsCount As Long
ReturnType As String
End Type
Public Type INTERFACE_INFO
Ptr As LongPtr
GUID As String
LCID As Long
memidConstructor As Long
memidDestructor As Long
Name As String
MembersCount As Long
InterfacesCount As Long
wMajorVerNum As Integer
wMinorVerNum As Integer
IMPLTYPEFLAGS As Long
End Type
Public Type SPECIAL_ENUMS
'Special vba ENUMS not defined in the enumerations module.
Caption() As String
Value() As String
End Type
Public Type ENUM_VALS
Name As String
Value As String
End Type
Public Type TEXT_STRUCT
Caption As String
Value As String
End Type
Private Type GUID
Data1 As Long
Data2 As Integer
Data3 As Integer
Data4(0& To 7&) As Byte
End Type
Private Type DUMMYUNIONNAME_TYPE
oInst As Long
lpvarValue As LongPtr
End Type
Private Type VARDESC
memid As Long
lpstrSchema As LongPtr
DUMMYUNIONNAME As LongPtr
elemdescVar As Long
wVarFlags As Long
varkind As Long
End Type
Private Type TTYPEDESC
pTypeDesc As LongPtr
vt As Integer
End Type
Private Type TPARAMDESC
pPARAMDESCEX As LongPtr
wParamFlags As Integer
End Type
Private Type TELEMDESC
tdesc As TTYPEDESC
pdesc As TPARAMDESC
End Type
Private Type TYPEATTR
aGUID As GUID
LCID As Long
dwReserved As Long
memidConstructor As Long
memidDestructor As Long
lpstrSchema As LongPtr
cbSizeInstance As Integer
typekind As Long
cFuncs As Integer
cVars As Integer
cImplTypes As Integer
cbSizeVft As Integer
cbAlignment As Integer
wTypeFlags As Integer
wMajorVerNum As Integer
wMinorVerNum As Integer
tdescAlias As Long
idldescType As Long
End Type
Private Type FUNCDESC
memid As Long
lReserved1 As LongPtr
lprgelemdescParam As LongPtr
funckind As Long
INVOKEKIND As Long
CallConv As Long
cParams As Integer
cParamsOpt As Integer
oVft As Integer
cReserved2 As Integer
elemdescFunc As TELEMDESC
wFuncFlags As Integer
End Type
Private Type MODULEINFO
lpBaseOfDll As LongPtr
SizeofImage As Long
EntryPoint As LongPtr
End Type
Private Type INFO
CI() As INTERFACE_INFO
MI() As INTERFACE_INFO
EI() As INTERFACE_INFO
DI() As INTERFACE_INFO
End Type
Public Type ARRAYS
arrClasses() As INTERFACE_INFO
arrInterfaces() As INTERFACE_INFO
arrDisps() As INTERFACE_INFO
arrModules() As INTERFACE_INFO
arrEnums() As INTERFACE_INFO
arrTypes() As SEARCH_TARGET
arrNames() As String
arrFuncPtrs() As FUNC_INFO
arrEnumPtrs() As ENUM_VALS
arrPtrs() As LongPtr
arrOtherInfo1() As TEXT_STRUCT
arrOtherInfo2() As TEXT_STRUCT
arrImplTypeFlags() As Long 'event flags
End Type
Public tArrays As ARRAYS
Private hFrame As LongPtr, hDC As LongPtr, hOldFont As LongPtr, lOldBKMode As Long
Private tTextSize1 As Size, tTextSize2 As Size, tTextSize3 As Size
Private tTextRect1 As RECT, tTextRect2 As RECT, tTextRect3 As RECT
Private sWaitMsg1 As String, sWaitMsg2 As String
Private bExportingFinished As Boolean
Private bErrorFlag As Boolean
Function RetrieveLibInfo(ByVal sFile As String) As Boolean
Dim lArrRows As Long, i As Long, j As Long
Call EraseArrays
With tArrays
.arrClasses = TypeInfoFromCOMLib(sFile, CI).CI
If (Not Not .arrClasses) = False Then
Exit Function
End If
For i = LBound(.arrClasses) To UBound(.arrClasses)
.arrInterfaces = InterFacesFromClass(.arrClasses(i))
For j = LBound(.arrInterfaces) To UBound(.arrInterfaces)
ReDim Preserve .arrNames(lArrRows)
ReDim Preserve .arrPtrs(lArrRows)
ReDim Preserve .arrTypes(lArrRows)
ReDim Preserve .arrImplTypeFlags(lArrRows)
ReDim Preserve .arrOtherInfo1(lArrRows)
ReDim Preserve .arrOtherInfo2(lArrRows)
.arrNames(lArrRows) = ChrW(&H25A0) & " " & .arrInterfaces(j).Name
.arrPtrs(lArrRows) = .arrInterfaces(j).Ptr
.arrTypes(lArrRows) = Class_
.arrImplTypeFlags(lArrRows) = .arrInterfaces(j).IMPLTYPEFLAGS
.arrOtherInfo1(lArrRows) = BuildClassInfoString(.arrInterfaces(j), False)
.arrOtherInfo2(lArrRows) = BuildClassInfoString(.arrInterfaces(j), True)
lArrRows = lArrRows + 1&
Next j
Next i
.arrDisps = TypeInfoFromCOMLib(sFile, DI).DI
If Not Not .arrDisps Then
For i = LBound(.arrDisps) To UBound(.arrDisps)
ReDim Preserve .arrNames(lArrRows)
ReDim Preserve .arrPtrs(lArrRows)
ReDim Preserve .arrTypes(lArrRows)
ReDim Preserve .arrOtherInfo1(lArrRows)
ReDim Preserve .arrOtherInfo2(lArrRows)
.arrNames(lArrRows) = ChrW(&H25A0) & " " & .arrDisps(i).Name
.arrPtrs(lArrRows) = .arrDisps(i).Ptr
.arrTypes(lArrRows) = Interface_
.arrOtherInfo1(lArrRows) = BuildClassInfoString(.arrDisps(i), False)
.arrOtherInfo2(lArrRows) = BuildClassInfoString(.arrDisps(i), True)
lArrRows = lArrRows + 1&
Next
End If
.arrModules = TypeInfoFromCOMLib(sFile, MI).MI
If Not Not .arrModules Then
For i = LBound(.arrModules) To UBound(.arrModules)
ReDim Preserve .arrNames(lArrRows)
ReDim Preserve .arrPtrs(lArrRows)
ReDim Preserve .arrTypes(lArrRows)
ReDim Preserve .arrOtherInfo1(lArrRows)
ReDim Preserve .arrOtherInfo2(lArrRows)
.arrNames(lArrRows) = ChrW(&H25E5) & " " & .arrModules(i).Name
.arrPtrs(lArrRows) = .arrModules(i).Ptr
.arrTypes(lArrRows) = Module_
.arrOtherInfo1(lArrRows) = BuildClassInfoString(.arrModules(i), False)
.arrOtherInfo2(lArrRows) = BuildClassInfoString(.arrModules(i), True)
lArrRows = lArrRows + 1&
Next i
End If
.arrEnums = TypeInfoFromCOMLib(sFile, EI).EI
If Not Not .arrEnums Then
For i = LBound(.arrEnums) To UBound(.arrEnums)
ReDim Preserve .arrNames(lArrRows)
ReDim Preserve .arrPtrs(lArrRows)
ReDim Preserve .arrTypes(lArrRows)
ReDim Preserve .arrOtherInfo1(lArrRows)
ReDim Preserve .arrOtherInfo2(lArrRows)
.arrNames(lArrRows) = ChrW(&H25CD) & " " & .arrEnums(i).Name
.arrPtrs(lArrRows) = .arrEnums(i).Ptr
.arrTypes(lArrRows) = Enum_
.arrOtherInfo1(lArrRows) = BuildClassInfoString(.arrEnums(i), False)
.arrOtherInfo2(lArrRows) = BuildClassInfoString(.arrEnums(i), True)
lArrRows = lArrRows + 1&
Next i
End If
End With
RetrieveLibInfo = True
End Function
Sub EraseArrays()
With tArrays
Erase .arrClasses(): Erase .arrInterfaces()
Erase .arrDisps(): Erase .arrModules()
Erase .arrEnums(): Erase .arrTypes()
Erase .arrNames(): Erase .arrFuncPtrs()
Erase .arrEnumPtrs(): Erase .arrPtrs()
Erase .arrOtherInfo1(): Erase .arrOtherInfo2()
Erase .arrImplTypeFlags()
End With
End Sub
Function TypeInfoFromCOMLib(ByVal sLibFile As String, ByVal eRequestedInfo As TKIND) As INFO
Const REGKIND_NONE = 2&, MEMBERID_NIL = -1&
Const TKIND_COCLASS = 5&, TKIND_MODULE = 2&, TKIND_ENUM = 0&, TKIND_DISPATCH = 4&
Const S_OK = 0&, CC_STDCALL = 4&
Dim pTKind As LongPtr, ppTInfo As LongPtr, farPtr As LongPtr, psGUID As LongPtr
Dim tClassInfo As INTERFACE_INFO, tModuleInfo As INTERFACE_INFO
Dim tDispInfo As INTERFACE_INFO, tEnumInfo As INTERFACE_INFO
Dim tInfoArray As INFO
Dim tTYPEATTR As TYPEATTR
Dim unkTypLib As stdole.IUnknown
Dim i As Long, j As Long, lRet As Long, lInfoCount As Long
Dim sName As String
lRet = LoadTypeLibEx(StrPtr(sLibFile), REGKIND_NONE, unkTypLib)
If lRet <> S_OK Then
MsgBox "Unable to load the " & sLibFile & " library.": Exit Function
End If
lInfoCount = vtblCall(ObjPtr(unkTypLib), 3& * PTR_LEN, vbLong, CC_STDCALL) 'ITypeLib::GetTypeInfoCount
For i = 0& To lInfoCount - 1&
lRet = vtblCall(ObjPtr(unkTypLib), 5& * PTR_LEN, vbLong, CC_STDCALL, i, VarPtr(pTKind)) ' ITypeLib::GetTypeInfoType
If lRet <> S_OK Then
MsgBox "Unable to retrieve the type of a type description.": Exit Function
End If
If pTKind = eRequestedInfo Then
Select Case eRequestedInfo
Case Is = CI
ReDim Preserve tInfoArray.CI(j)
Case Is = MI
ReDim Preserve tInfoArray.MI(j)
Case Is = DI
ReDim Preserve tInfoArray.DI(j)
Case Is = EI
ReDim Preserve tInfoArray.EI(j)
End Select
lRet = vtblCall(ObjPtr(unkTypLib), 4& * PTR_LEN, vbLong, CC_STDCALL, i, VarPtr(ppTInfo)) 'ITypeLib::GetTypeInfo
If lRet <> S_OK Then
MsgBox "Unable to retrieve the specified type description in the library.": Exit Function
End If
lRet = vtblCall(ppTInfo, 3& * PTR_LEN, vbLong, CC_STDCALL, VarPtr(farPtr)) 'ITypeInfo::GetTypeAttr
If lRet <> S_OK Then
MsgBox "Unable to retrieve a TYPEATTR structure that contains the attributes of the type description."
Exit Function
End If
Call CopyMemory(tTYPEATTR, ByVal farPtr, LenB(tTYPEATTR))
lRet = vtblCall(ppTInfo, 19& * PTR_LEN, vbEmpty, CC_STDCALL, farPtr) 'ITypeInfo::ReleaseTypeAttr
Call StringFromIID(tTYPEATTR.aGUID, VarPtr(psGUID))
lRet = vtblCall(ppTInfo, 12& * PTR_LEN, vbLong, CC_STDCALL, MEMBERID_NIL, VarPtr(sName), NULL_PTR, NULL_PTR, NULL_PTR) 'ITypeInfo::GetDocumentation
If lRet <> S_OK Then
MsgBox "Unable to retrieve the documentation string.": Exit Function
End If
Select Case pTKind
Case Is = TKIND_COCLASS
With tClassInfo
.Ptr = ppTInfo
.GUID = GetStrFromPtrW(psGUID)
.LCID = tTYPEATTR.LCID
.memidConstructor = tTYPEATTR.memidConstructor
.memidDestructor = tTYPEATTR.memidDestructor
.Name = sName
.MembersCount = tTYPEATTR.cFuncs
.InterfacesCount = tTYPEATTR.cImplTypes
.wMajorVerNum = tTYPEATTR.wMajorVerNum
.wMinorVerNum = tTYPEATTR.wMinorVerNum
End With
tInfoArray.CI(j) = tClassInfo
Case Is = TKIND_MODULE
With tModuleInfo
.Ptr = ppTInfo
.GUID = GetStrFromPtrW(psGUID)
.LCID = tTYPEATTR.LCID
.memidConstructor = tTYPEATTR.memidConstructor
.memidDestructor = tTYPEATTR.memidDestructor
.Name = sName
.MembersCount = tTYPEATTR.cFuncs
.InterfacesCount = tTYPEATTR.cImplTypes '
.wMajorVerNum = tTYPEATTR.wMajorVerNum
.wMinorVerNum = tTYPEATTR.wMinorVerNum
End With
tInfoArray.MI(j) = tModuleInfo
Case Is = TKIND_DISPATCH
With tDispInfo
.Ptr = ppTInfo
.GUID = GetStrFromPtrW(psGUID)
.LCID = tTYPEATTR.LCID
.memidConstructor = tTYPEATTR.memidConstructor
.memidDestructor = tTYPEATTR.memidDestructor
.Name = sName
.MembersCount = tTYPEATTR.cFuncs
.InterfacesCount = tTYPEATTR.cImplTypes
.wMajorVerNum = tTYPEATTR.wMajorVerNum
.wMinorVerNum = tTYPEATTR.wMinorVerNum
End With
tInfoArray.DI(j) = tDispInfo
Case Is = TKIND_ENUM
With tEnumInfo
.Ptr = ppTInfo
.GUID = GetStrFromPtrW(psGUID)
.LCID = tTYPEATTR.LCID
.memidConstructor = tTYPEATTR.memidConstructor
.memidDestructor = tTYPEATTR.memidDestructor
.Name = sName
.MembersCount = tTYPEATTR.cVars
.wMajorVerNum = tTYPEATTR.wMajorVerNum
.wMinorVerNum = tTYPEATTR.wMinorVerNum
End With
tInfoArray.EI(j) = tEnumInfo
End Select
j = j + 1&
End If
Next
TypeInfoFromCOMLib = tInfoArray
End Function
Function GetFuncs( _
ByVal ppTInfo As LongPtr, _
ByVal ImpEvent As IMPLTYPEFLAGS, _
Optional ByVal FuncCallType As VbCallType, _
Optional ByVal unk As Boolean _
) As FUNC_INFO()
Const CC_STDCALL = 4&, S_OK = 0&
Dim aTYPEATTR() As LongPtr, aFUNCDESC() As LongPtr, farPtr As LongPtr
Dim tTYPEATTR As TYPEATTR, tFuncDesc As FUNCDESC, tFuncDescArray() As FUNC_INFO
Dim aGUID(0& To 11&) As Long
Dim lRet As Long, lFuncsCount As Long, n As Long
Dim sFuncName As String
Dim IUnkIDisp As Variant
lRet = vtblCall(ppTInfo, 3& * PTR_LEN, vbLong, CC_STDCALL, VarPtr(farPtr)) 'ITypeInfo::GetTypeAttr
If lRet <> S_OK Then
MsgBox "Unable to retrieve a TYPEATTR structure that contains the attributes of the type description."
Exit Function
End If
Call CopyMemory(ByVal VarPtr(tTYPEATTR), ByVal farPtr, LenB(tTYPEATTR))
ReDim aTYPEATTR(LenB(tTYPEATTR))
Call CopyMemory(ByVal VarPtr(aTYPEATTR(0&)), tTYPEATTR, UBound(aTYPEATTR))
lRet = vtblCall(ppTInfo, 19& * PTR_LEN, vbEmpty, CC_STDCALL, farPtr) 'ITypeInfo::ReleaseTypeAttr
If tTYPEATTR.cFuncs Then
For lFuncsCount = 0& To tTYPEATTR.cVars + tTYPEATTR.cFuncs - 1&
lRet = vtblCall(ppTInfo, 5& * PTR_LEN, vbLong, CC_STDCALL, lFuncsCount, VarPtr(farPtr)) 'ITypeInfo::GetFuncDesc
If farPtr = NULL_PTR Then Exit Function
If lRet <> S_OK Then
MsgBox "Unable to retrieve the FUNCDESC structure that contains information about a specified function."
Exit Function
End If
If farPtr = NULL_PTR Then GoTo SkipFunc
Call CopyMemory(ByVal VarPtr(tFuncDesc), ByVal farPtr, LenB(tFuncDesc))
ReDim aFUNCDESC(LenB(tFuncDesc))
Call CopyMemory(ByVal VarPtr(aFUNCDESC(0)), tFuncDesc, UBound(aFUNCDESC))
lRet = vtblCall(ppTInfo, 20& * PTR_LEN, vbEmpty, CC_STDCALL, farPtr) 'ITypeInfo::ReleaseFuncDesc
lRet = vtblCall(ppTInfo, 12& * PTR_LEN, vbLong, CC_STDCALL, aFUNCDESC(0), VarPtr(sFuncName), NULL_PTR, NULL_PTR, NULL_PTR) 'ITypeInfo::GetDocumentation
If lRet <> S_OK Then
MsgBox "Unable to retrieve the documentation string.": Exit Function
End If
IUnkIDisp = Array("QueryInterface", "AddRef", "Release", "GetTypeInfoCount", "GetTypeInfo", "GetIDsOfNames", "Invoke")
If IsError(Application.Match(sFuncName, IUnkIDisp, 0&)) = False And unk = False Then GoTo SkipFunc
With tFuncDesc
If (.INVOKEKIND And FuncCallType) = .INVOKEKIND Then
ReDim Preserve tFuncDescArray(n)
tFuncDescArray(n).Name = sFuncName
tFuncDescArray(n).memid = .memid
tFuncDescArray(n).CallConvention = .CallConv
tFuncDescArray(n).funckind = .funckind
tFuncDescArray(n).VTBLOffset = .oVft
If ImpEvent And (IMPLTYPEFLAG_FDEFAULT Or IMPLTYPEFLAG_FSOURCE) = ImpEvent Then
If IsError(Application.Match(sFuncName, IUnkIDisp, 0&)) Then
tFuncDescArray(n).INVOKEKIND = "VbMethod [Event]"
Else
tFuncDescArray(n).INVOKEKIND = Switch(.INVOKEKIND = 1&, "VbMethod", .INVOKEKIND = 2&, "VbGet", .INVOKEKIND = 4&, "VbLet", .INVOKEKIND = 8&, "VbSet")
End If
Else
tFuncDescArray(n).INVOKEKIND = Switch(.INVOKEKIND = 1&, "VbMethod", .INVOKEKIND = 2&, "VbGet", .INVOKEKIND = 4&, "VbLet", .INVOKEKIND = 8&, "VbSet")
End If
tFuncDescArray(n).ParamsCount = .cParams
tFuncDescArray(n).OptParamsCount = .cParamsOpt
tFuncDescArray(n).ReturnType = ReturnType(.elemdescFunc.tdesc.vt)
n = n + 1&
End If
End With
SkipFunc:
If lFuncsCount Mod 100& = 0& Then DoEvents
Next
GetFuncs = tFuncDescArray
End If
End Function
Function GetClassAttributes(ByVal sLibFile As String, ByVal pFindTypeInfo As LongPtr) As INTERFACE_INFO
Const REGKIND_NONE = 2&, MEMBERID_NIL = -1&, TKIND_ENUM = 0&
Const S_OK = 0&, CC_STDCALL = 4&
Dim pTKind As LongPtr, ppTInfo As LongPtr, farPtr As LongPtr, psGUID As LongPtr
Dim tClassInfo As INTERFACE_INFO, tTYPEATTR As TYPEATTR
Dim unkTypLib As stdole.IUnknown
Dim i As Long, lRet As Long, lInfoCount As Long
Dim sTypeInfoName As String
lRet = LoadTypeLibEx(StrPtr(sLibFile), REGKIND_NONE, unkTypLib)
If lRet <> S_OK Then
MsgBox "Unable to load the " & sLibFile & " library.": Exit Function
End If
lInfoCount = vtblCall(ObjPtr(unkTypLib), 3& * PTR_LEN, vbLong, CC_STDCALL) 'ITypeLib::GetTypeInfoCount
For i = 0& To lInfoCount - 1&
lRet = vtblCall(ObjPtr(unkTypLib), 5& * PTR_LEN, vbLong, CC_STDCALL, i, VarPtr(pTKind)) ' ITypeLib::GetTypeInfoType
If lRet <> S_OK Then
MsgBox "Unable to retrieve the type of a type description.": Exit Function
End If
lRet = vtblCall(ObjPtr(unkTypLib), 4& * PTR_LEN, vbLong, CC_STDCALL, i, VarPtr(ppTInfo)) 'ITypeLib::GetTypeInfo
If lRet <> S_OK Then
MsgBox "Unable to retrieve the specified type description in the library.": Exit Function
End If
lRet = vtblCall(ppTInfo, 3& * PTR_LEN, vbLong, CC_STDCALL, VarPtr(farPtr)) 'ITypeInfo::GetTypeAttr
If lRet <> S_OK Then
MsgBox "Unable to retrieve a TYPEATTR structure that contains the attributes of the type description."
Exit Function
End If
Call CopyMemory(tTYPEATTR, ByVal farPtr, LenB(tTYPEATTR))
lRet = vtblCall(ppTInfo, 19& * PTR_LEN, vbEmpty, CC_STDCALL, farPtr) 'ITypeInfo::ReleaseTypeAttr
Call StringFromIID(tTYPEATTR.aGUID, VarPtr(psGUID))
lRet = vtblCall(ppTInfo, 12& * PTR_LEN, vbLong, CC_STDCALL, MEMBERID_NIL, VarPtr(sTypeInfoName), NULL_PTR, NULL_PTR, NULL_PTR) 'ITypeInfo::GetDocumentation
If lRet <> S_OK Then
MsgBox "Unable to retrieve the documentation string.": Exit Function
End If
If pFindTypeInfo = ppTInfo And pTKind <> TKIND_ENUM Then
With tClassInfo
.Ptr = pFindTypeInfo
.GUID = GetStrFromPtrW(psGUID)
.LCID = tTYPEATTR.LCID
.memidConstructor = tTYPEATTR.memidConstructor
.memidDestructor = tTYPEATTR.memidDestructor
.Name = sTypeInfoName
.MembersCount = tTYPEATTR.cFuncs
.InterfacesCount = tTYPEATTR.cImplTypes
.wMajorVerNum = tTYPEATTR.wMajorVerNum
.wMinorVerNum = tTYPEATTR.wMinorVerNum
End With
Exit For
End If
Next
GetClassAttributes = tClassInfo
End Function
Function MembersFromEnum(pEnum As LongPtr) As ENUM_VALS()
Const S_OK = 0&, CC_STDCALL = 4&
Dim ppTypeAttr As LongPtr, pcNames As LongPtr
Dim tTYPEATTR As TYPEATTR, tVARDESC As VARDESC
Dim tDUMMYUNIONNAME As DUMMYUNIONNAME_TYPE, lEnumVal As Long
Dim pVARDESC As LongPtr, BstrName As String
Dim vRet() As ENUM_VALS
Dim i As Long, lRet As Long, lOffset As Long
lRet = vtblCall(pEnum, 3& * PTR_LEN, vbLong, CC_STDCALL, VarPtr(ppTypeAttr)) 'ITypeInfo::GetTypeAttr
If lRet <> S_OK Then
MsgBox "Unable to retrieve a TYPEATTR structure that contains the attributes of the type description."
Exit Function
End If
If ppTypeAttr = NULL_PTR Then Exit Function
Call CopyMemory(ByVal VarPtr(tTYPEATTR), ByVal ppTypeAttr, LenB(tTYPEATTR))
lRet = vtblCall(pEnum, 19& * PTR_LEN, vbEmpty, CC_STDCALL, ppTypeAttr) 'ITypeInfo::ReleaseTypeAttr
ReDim vRet(tTYPEATTR.cVars - 1&)
For i = 0& To tTYPEATTR.cVars - 1&
lRet = vtblCall(pEnum, 6& * PTR_LEN, vbLong, CC_STDCALL, i, VarPtr(pVARDESC)) 'ITypeInfo::GetVarDesc
If lRet <> S_OK Then
MsgBox "Unable to retrieves a VARDESC structure that describes the specified variable."
Exit Function
End If
Call CopyMemory(ByVal VarPtr(tVARDESC), ByVal pVARDESC, LenB(tVARDESC))
lRet = vtblCall(pEnum, 7& * PTR_LEN, vbLong, CC_STDCALL, tVARDESC.memid, VarPtr(BstrName), tTYPEATTR.cVars, VarPtr(pcNames)) 'ITypeInfo::GetNames
If lRet <> S_OK Then
MsgBox "Unable to retrieves the variable with the specified member ID or the name of the property or method."
Exit Function
End If
lOffset = IIf(PTR_LEN = 4&, 4&, 0&)
Call CopyMemory(tDUMMYUNIONNAME, ByVal tVARDESC.DUMMYUNIONNAME + lOffset, LenB(tDUMMYUNIONNAME))
Call CopyMemory(lEnumVal, ByVal VarPtr(tDUMMYUNIONNAME.lpvarValue), PTR_LEN)
vRet(i).Name = BstrName
vRet(i).Value = lEnumVal
MembersFromEnum = vRet
Next i
End Function
Function BuildFuncInfoString(INFO As FUNC_INFO) As TEXT_STRUCT
Dim tString As TEXT_STRUCT
With tString
.Caption = _
"[Member Name:]" & vbLf & _
"[INVOKEKIND:]" & vbLf & _
"[memid:]" & vbLf & _
"[ParamsCount:]" & vbLf & _
"[Opt ParamsCount:]" & vbLf & _
"[Funckind:]" & vbLf & _
"[VTBLOffset:]" & vbLf & _
"[CallConvention:]" & vbLf & _
"[ReturnType:]"
.Value = _
INFO.Name & vbLf & _
INFO.INVOKEKIND & vbLf & _
INFO.memid & vbLf & _
INFO.ParamsCount & vbLf & _
INFO.OptParamsCount & vbLf & _
INFO.funckind & vbLf & _
Hex(INFO.VTBLOffset) & vbLf & _
INFO.CallConvention & vbLf & _
INFO.ReturnType
End With
BuildFuncInfoString = tString
End Function
Function BuildEnumInfoString(INFO As ENUM_VALS) As TEXT_STRUCT
Dim tString As TEXT_STRUCT
With tString
.Caption = _
"[Const Name:]" & vbLf & _
"[Value:]"
.Value = _
INFO.Name & vbLf & _
INFO.Value
End With
BuildEnumInfoString = tString
End Function
Function GUIDFromLib(ByVal LibPathName As String) As String
Const REGKIND_NONE = 2&, S_OK = 0&, CC_STDCALL = 4&
Dim ppTLibAttr As LongPtr, psGUID As LongPtr
Dim unkTypLib As stdole.IUnknown, tTYPEATTR As TYPEATTR
Dim lRet As Long, sGUID As String
lRet = LoadTypeLibEx(StrPtr(LibPathName), REGKIND_NONE, unkTypLib)
lRet = vtblCall(ObjPtr(unkTypLib), 7& * PTR_LEN, vbLong, CC_STDCALL, VarPtr(ppTLibAttr)) 'ITypeLib:: GetLibAttr
If lRet = S_OK And ppTLibAttr Then
Call CopyMemory(tTYPEATTR, ByVal ppTLibAttr, LenB(tTYPEATTR))
Call StringFromIID(tTYPEATTR.aGUID, VarPtr(psGUID))
sGUID = GetStrFromPtrW(psGUID)
If Len(Trim(sGUID)) Then
GUIDFromLib = sGUID
End If
lRet = vtblCall(ObjPtr(unkTypLib), 12& * PTR_LEN, vbLong, CC_STDCALL, ppTLibAttr) 'ITypeLib:: ReleaseTLibAttr
End If
End Function
Function GUIDFromRefLib(ByVal LibPathName As String) As String
'[ Requires References :: Visual Basic for Applications Extensibility And Trust access to Visual Basic Project ]
Dim oRef As VBIDE.Reference, oRefs As VBIDE.References
Set oRefs = Application.VBE.ActiveVBProject.References
On Error Resume Next
For Each oRef In oRefs
If oRef.FullPath = LibPathName Then
GUIDFromRefLib = oRef.GUID: Exit For
End If
Next oRef
End Function
Function RefLibNameToFullPath(ByVal ReferenceLibName As String) As String
'[ Requires References :: Visual Basic for Applications Extensibility And Trust access to Visual Basic Project ]
Dim oRef As VBIDE.Reference, oRefs As VBIDE.References, i As Integer
On Error Resume Next
Set oRefs = Application.VBE.ActiveVBProject.References
For Each oRef In oRefs
i = i + 1&
If LCase(oRef.Name) = LCase(ReferenceLibName) Then
RefLibNameToFullPath = oRef.FullPath: Exit For
End If
Next oRef
End Function
Function GetVBEReferencesList() As String()
'[ Requires References :: Visual Basic for Applications Extensibility And Trust access to Visual Basic Project ]
Dim oRef As VBIDE.Reference, oRefs As VBIDE.References, i As Integer, tmpArray() As String
Set oRefs = Application.VBE.ActiveVBProject.References
For Each oRef In oRefs
ReDim Preserve tmpArray(i)
tmpArray(i) = oRef.Name: i = i + 1&
Next oRef
GetVBEReferencesList = tmpArray
End Function
Function GetSpecialEnum(sEnum As String) As Boolean
'Handle special vba constants not defined in the enumerations module.
Dim a() As Variant, v As Variant
a = Array("Constants", "KeyCodeConstants", "ColorConstants", "SystemColorConstants")
For Each v In a
If ChrW(&H25E5) & " " & v = sEnum Then
GetSpecialEnum = True: Exit Function
End If
Next v
End Function
Function BuildSpecailEnumValues(ByVal sEnum As String, Optional sPfx As String) As SPECIAL_ENUMS
Dim X() As String, Y() As String
Select Case sEnum
Case ChrW(&H25E5) & " " & "Constants"
ReDim X(10): ReDim Y(10)
X(0) = sPfx & "vbObjectError": Y(0) = -2147221504
X(1) = sPfx & "vbNullString": Y(1) = vbNullString
X(2) = sPfx & "vbNullChar": Y(2) = vbNullChar
X(3) = sPfx & "vbCrLf": Y(3) = vbCrLf
X(4) = sPfx & "vbNewLine": Y(4) = vbNewLine
X(5) = sPfx & "vbCr": Y(5) = vbCr
X(6) = sPfx & "vbLf": Y(6) = vbLf
X(7) = sPfx & "vbBack": Y(7) = vbBack
X(8) = sPfx & "vbFormFeed": Y(8) = vbFormFeed
X(9) = sPfx & "vbTab": Y(9) = vbTab
X(10) = sPfx & "vbVerticalTab": Y(10) = vbVerticalTab
Case ChrW(&H25E5) & " " & "KeyCodeConstants"
ReDim X(98): ReDim Y(98)
X(0) = sPfx & "vbKeyLButton": Y(0) = 1
X(1) = sPfx & "vbKeyRButton": Y(1) = 2
X(2) = sPfx & "vbKeyCancel": Y(2) = 3
X(3) = sPfx & "vbKeyMButton": Y(3) = 4
X(4) = sPfx & "vbKeyBack": Y(4) = 8
X(5) = sPfx & "vbKeyTab": Y(5) = 9
X(6) = sPfx & "vbKeyClear": Y(6) = 12
X(7) = sPfx & "vbKeyReturn": Y(7) = 13
X(8) = sPfx & "vbKeyShift": Y(8) = 16
X(9) = sPfx & "vbKeyControl": Y(9) = 17
X(10) = sPfx & "vbKeyMenu": Y(10) = 18
X(11) = sPfx & "vbKeyPause": Y(11) = 19
X(12) = sPfx & "vbKeyCapital": Y(12) = 20
X(13) = sPfx & "vbKeyEscape": Y(13) = 27
X(14) = sPfx & "vbKeySpace": Y(14) = 32
X(15) = sPfx & "vbKeyPageUp": Y(15) = 33
X(16) = sPfx & "vbKeyPageDown": Y(16) = 34
X(17) = sPfx & "vbKeyEnd": Y(17) = 35
X(18) = sPfx & "vbKeyHome": Y(18) = 36
X(19) = sPfx & "vbKeyLeft": Y(19) = 37
X(20) = sPfx & "vbKeyUp": Y(20) = 38
X(21) = sPfx & "vbKeyRight": Y(21) = 39
X(22) = sPfx & "vbKeyDown": Y(22) = 40
X(23) = sPfx & "vbKeySelect": Y(23) = 41
X(24) = sPfx & "vbKeyPrint": Y(24) = 42
X(25) = sPfx & "vbKeyExecute": Y(25) = 43
X(26) = sPfx & "vbKeySnapshot": Y(26) = 44
X(27) = sPfx & "vbKeyInsert": Y(27) = 45
X(28) = sPfx & "vbKeyDelete": Y(28) = 46
X(29) = sPfx & "vbKeyHelp": Y(29) = 47
X(30) = sPfx & "vbKeyNumlock": Y(30) = 144
X(31) = sPfx & "vbKeyA": Y(31) = 65
X(32) = sPfx & "vbKeyB": Y(32) = 66
X(33) = sPfx & "vbKeyC": Y(33) = 67
X(34) = sPfx & "vbKeyD": Y(34) = 68
X(35) = sPfx & "vbKeyE": Y(35) = 69
X(36) = sPfx & "vbKeyF": Y(36) = 70
X(37) = sPfx & "vbKeyG": Y(37) = 71
X(38) = sPfx & "vbKeyH": Y(38) = 72
X(39) = sPfx & "vbKeyI": Y(39) = 73
X(40) = sPfx & "vbKeyJ": Y(40) = 74
X(41) = sPfx & "vbKeyK": Y(41) = 75
X(42) = sPfx & "vbKeyL": Y(42) = 76
X(43) = sPfx & "vbKeyM": Y(43) = 77
X(44) = sPfx & "vbKeyN": Y(44) = 78
X(45) = sPfx & "vbKeyO": Y(45) = 79
X(46) = sPfx & "vbKeyP": Y(46) = 80
X(47) = sPfx & "vbKeyQ": Y(47) = 81
X(48) = sPfx & "vbKeyR": Y(48) = 82
X(49) = sPfx & "vbKeyS": Y(49) = 83
X(50) = sPfx & "vbKeyT": Y(50) = 84
X(51) = sPfx & "vbKeyU": Y(51) = 85
X(52) = sPfx & "vbKeyV": Y(52) = 86
X(53) = sPfx & "vbKeyW": Y(53) = 87
X(54) = sPfx & "vbKeyX": Y(54) = 88
X(55) = sPfx & "vbKeyY": Y(55) = 89
X(56) = sPfx & "vbKeyZ": Y(56) = 90
X(57) = sPfx & "vbKey0": Y(57) = 48
X(58) = sPfx & "vbKey1": Y(58) = 49
X(59) = sPfx & "vbKey2": Y(59) = 50
X(60) = sPfx & "vbKey3": Y(60) = 51
X(61) = sPfx & "vbKey4": Y(61) = 52
X(62) = sPfx & "vbKey5": Y(62) = 53
X(63) = sPfx & "vbKey6": Y(63) = 54
X(64) = sPfx & "vbKey7": Y(64) = 55
X(65) = sPfx & "vbKey8": Y(65) = 56
X(66) = sPfx & "vbKey9": Y(66) = 57
X(67) = sPfx & "vbKeyNumpad0": Y(67) = 96
X(68) = sPfx & "vbKeyNumpad1": Y(68) = 97
X(69) = sPfx & "vbKeyNumpad2": Y(69) = 98
X(70) = sPfx & "vbKeyNumpad3": Y(70) = 99
X(71) = sPfx & "vbKeyNumpad4": Y(71) = 100
X(72) = sPfx & "vbKeyNumpad5": Y(72) = 101
X(73) = sPfx & "vbKeyNumpad6": Y(73) = 102
X(74) = sPfx & "vbKeyNumpad7": Y(74) = 103
X(75) = sPfx & "vbKeyNumpad8": Y(75) = 104
X(76) = sPfx & "vbKeyNumpad9": Y(76) = 105
X(77) = sPfx & "vbKeyMultiply": Y(77) = 106
X(78) = sPfx & "vbKeyAdd": Y(78) = 107
X(79) = sPfx & "vbKeySeparator": Y(79) = 108
X(80) = sPfx & "vbKeySubtract": Y(80) = 109
X(81) = sPfx & "vbKeyDecimal": Y(81) = 110
X(82) = sPfx & "vbKeyDivide": Y(82) = 111
X(83) = sPfx & "vbKeyF1": Y(83) = 112
X(84) = sPfx & "vbKeyF2": Y(84) = 113
X(85) = sPfx & "vbKeyF3": Y(85) = 114
X(86) = sPfx & "vbKeyF4": Y(86) = 115
X(87) = sPfx & "vbKeyF5": Y(87) = 116
X(88) = sPfx & "vbKeyF6": Y(88) = 117
X(89) = sPfx & "vbKeyF7": Y(89) = 118
X(90) = sPfx & "vbKeyF8": Y(90) = 119
X(91) = sPfx & "vbKeyF9": Y(91) = 120
X(92) = sPfx & "vbKeyF10": Y(92) = 121
X(93) = sPfx & "vbKeyF11": Y(93) = 122
X(94) = sPfx & "vbKeyF12": Y(94) = 123
X(95) = sPfx & "vbKeyF13": Y(95) = 124
X(96) = sPfx & "vbKeyF14": Y(96) = 125
X(97) = sPfx & "vbKeyF15": Y(97) = 126
X(98) = sPfx & "vbKeyF16": Y(98) = 127
Case ChrW(&H25E5) & " " & "ColorConstants"
ReDim X(7): ReDim Y(7)
X(0) = sPfx & "vbBlack": Y(0) = 0
X(1) = sPfx & "vbRed": Y(1) = 255
X(2) = sPfx & "vbGreen": Y(2) = 65280
X(3) = sPfx & "vbYellow": Y(3) = 65535
X(4) = sPfx & "vbBlue": Y(4) = 16711680
X(5) = sPfx & "vbMagenta": Y(5) = 16711935
X(6) = sPfx & "vbCyan": Y(6) = 16776960
X(7) = sPfx & "vbWhite": Y(7) = 16777215
Case ChrW(&H25E5) & " " & "SystemColorConstants"
ReDim X(28): ReDim Y(28)
X(0) = sPfx & "vbScrollBars": Y(0) = -2147483648#
X(1) = sPfx & "vbDesktop": Y(1) = -2147483647
X(2) = sPfx & "vbActiveTitleBar": Y(2) = -2147483646
X(3) = "vbInactiveTitleBar": Y(3) = -2147483645
X(4) = sPfx & "vbMenuBar": Y(4) = -2147483644
X(5) = sPfx & "vbWindowBackground": Y(5) = -2147483643
X(6) = sPfx & "vbWindowFrame": Y(6) = -2147483642
X(7) = sPfx & "vbMenuText": Y(7) = -2147483641
X(8) = sPfx & "vbWindowText": Y(8) = -2147483640
X(9) = sPfx & "vbTitleBarText": Y(9) = -2147483639
X(10) = sPfx & "vbActiveBorder": Y(10) = -2147483638
X(11) = sPfx & "vbInactiveBorder": Y(11) = -2147483637
X(12) = sPfx & "vbApplicationWorkspace": Y(12) = -2147483636
X(13) = sPfx & "vbHighlight": Y(13) = -2147483635
X(14) = sPfx & "vbHighlightText": Y(14) = -2147483634
X(15) = sPfx & "vbButtonFace": Y(15) = -2147483633
X(16) = sPfx & "vbButtonShadow": Y(16) = -2147483632
X(17) = sPfx & "vbGrayText": Y(17) = -2147483631
X(18) = sPfx & "vbButtonText": Y(18) = -2147483630
X(19) = sPfx & "vbInactiveCaptionText": Y(19) = -2147483629
X(20) = sPfx & "vb3DHighlight": Y(20) = -2147483628
X(21) = sPfx & "vb3DFace": Y(21) = -2147483633
X(22) = sPfx & "vbMsgBox": Y(22) = -2147483625
X(23) = sPfx & "vbMsgBoxText": Y(23) = -2147483624
X(24) = sPfx & "vb3DShadow": Y(24) = -2147483632
X(25) = sPfx & "vb3DDKShadow": Y(25) = -2147483627
X(26) = sPfx & "vb3DLight": Y(26) = -2147483626
X(27) = sPfx & "vbInfoText": Y(27) = -2147483625
X(28) = sPfx & "vbInfoBackground": Y(28) = -2147483624
End Select
BuildSpecailEnumValues.Caption = X: BuildSpecailEnumValues.Value = Y
End Function
Function GetModulesBaseNamesFromCurrentProcess() As String()
Const MAX_PATH = 1024&, MAX_NUM_OF_MODULES = 1024&, HANDLE_SIZE = PTR_LEN, REGKIND_NONE = 2&
Dim hModuleHandles(MAX_NUM_OF_MODULES) As LongPtr
Dim hProc As LongPtr
Dim sModName As String
Dim sModBaseName As String
Dim sModPath As String
Dim tModInfo As MODULEINFO
Dim lBytesNeeded As Long, lModCount As Long, i As Long, j As Long, lStrLen As Long
Dim sModulesWithEmbeddedTlbsArray() As String
Dim unkTypLib As stdole.IUnknown, lRet As Long
hProc = GetCurrentProcess
If EnumProcessModules(hProc, hModuleHandles(0&), (MAX_NUM_OF_MODULES * HANDLE_SIZE), lBytesNeeded) = False Then
Debug.Print "EnumProcessModules failed"
Exit Function
End If
lModCount = lBytesNeeded \ HANDLE_SIZE
For i = 0& To lModCount - 1&
If hModuleHandles(i) = 0& Then
GoTo skipModule
End If
If GetModuleInformation(hProc, hModuleHandles(i), tModInfo, lBytesNeeded) = 0& Then
GoTo skipModule
End If
sModName = Space(MAX_PATH + 1&)
lStrLen = GetModuleFileNameExW(hProc, hModuleHandles(i), StrPtr(sModName), Len(sModName))
sModPath = Mid(sModName, 1&, lStrLen)
lRet = LoadTypeLibEx(StrPtr(sModPath), REGKIND_NONE, unkTypLib)
If lRet Then GoTo skipModule
ReDim Preserve sModulesWithEmbeddedTlbsArray(j)
lStrLen = GetModuleBaseNameW(hProc, hModuleHandles(i), StrPtr(sModName), Len(sModName))
sModBaseName = Mid(sModName, 1&, lStrLen)
sModulesWithEmbeddedTlbsArray(j) = sModBaseName: j = j + 1&
skipModule:
Next i
GetModulesBaseNamesFromCurrentProcess = sModulesWithEmbeddedTlbsArray
Erase hModuleHandles
Call CloseHandle(hProc)
End Function
'
Function ModuleBaseNameToFullPath(ByVal BaseName As String) As String
ModuleBaseNameToFullPath = ModuleFileName(BaseName)
End Function
Sub ExportTLibToSheet(ByVal sLib As String)
Dim i As Long, j As Long, Rw As Long
Dim sDecoration As String, sInvkind As String
Dim ImpEvent As IMPLTYPEFLAGS, sPrevEnum As String
Dim Funcs() As FUNC_INFO, Enums() As ENUM_VALS, lPtr As LongPtr
Dim tSPECIAL_ENUMS As SPECIAL_ENUMS
Dim oSh As Worksheet
If RetrieveLibInfo(sLib) = False Then GoTo Xit
Set oSh = Sheets.Add(, ActiveSheet)
oSh.Name = "Exported " & Right(sLib, Len(sLib) - InStrRev(sLib, "\", -1)) & "_" & Sheets.Count
oSh.[a2] = "* " & sLib
oSh.[a2].Font.Size = 14&
Rw = 3&
With tArrays
For i = LBound(.arrNames) To UBound(.arrNames)
lPtr = .arrPtrs(i)
If .arrTypes(i) <> Enum_ Then
Rw = Rw + 1&
oSh.Cells(Rw, 2&) = .arrNames(i)
If Not Not .arrImplTypeFlags Then
If i < UBound(.arrImplTypeFlags) Then
ImpEvent = .arrImplTypeFlags(i)
End If
End If
If GetSpecialEnum(.arrNames(i)) Then
tSPECIAL_ENUMS = BuildSpecailEnumValues(.arrNames(i), ChrW(&H2022) & " ")
If Not Not tSPECIAL_ENUMS.Caption Then
For j = LBound(tSPECIAL_ENUMS.Caption) To UBound(tSPECIAL_ENUMS.Caption)
Rw = Rw + 1&
oSh.Cells(Rw, 3&) = tSPECIAL_ENUMS.Caption(j)
oSh.Cells(Rw, 4&) = "Enum"
oSh.Cells(Rw, 5&) = tSPECIAL_ENUMS.Value(j)
Next j
End If
End If
Funcs = GetFuncs( _
lPtr, _
ImpEvent, _
VbLet + _
VbGet + _
VbSet + _
VbMethod, _
True _
)
If Not Not Funcs Then
For j = LBound(Funcs) To UBound(Funcs)
Rw = Rw + 1&
sInvkind = Funcs(j).INVOKEKIND
Select Case sInvkind
Case Is = "VbGet", "VbLet", "VbSet"
sDecoration = ChrW(&H25A6) & " "
Case Is = "VbMethod"
sDecoration = ChrW(&H25B1) & " "
Case Is = "VbMethod [Event]"
sDecoration = ChrW(&H2944) & " "
End Select
oSh.Cells(Rw, 3&) = sDecoration & Funcs(j).Name
oSh.Cells(Rw, 4&) = MemberKindToStandardMemberName(sInvkind, Funcs(j).ReturnType)
oSh.Cells(Rw, 5&) = IIf(InStr(sInvkind, "[Event]"), "VbMethod", sInvkind)
oSh.Cells(Rw, 6&) = Funcs(j).ReturnType
oSh.Cells(Rw, 7&) = Funcs(j).ParamsCount
oSh.Cells(Rw, 8&) = Funcs(j).OptParamsCount
oSh.Cells(Rw, 9&) = Funcs(j).VTBLOffset
oSh.Cells(Rw, 10&) = Funcs(j).memid
Next j
End If
Else
Enums = MembersFromEnum(lPtr)
If Not Not Enums Then
For j = LBound(Enums) To UBound(Enums)
If sPrevEnum <> .arrNames(i) Then
Rw = Rw + 1&
oSh.Cells(Rw, 2&) = .arrNames(i)
End If
Rw = Rw + 1&
sPrevEnum = .arrNames(i)
oSh.Cells(Rw, 3&) = Enums(j).Name
oSh.Cells(Rw, 4&) = "Enum"
oSh.Cells(Rw, 5&) = Enums(j).Value
Next j
End If
End If
Next i
End With
Call FormatExportSheet(oSh)
Exit Sub
Xit:
MsgBox "An error has occurred while exporting the tlb to the worksheet."
End Sub
Sub ShowWaitMsg(ByVal Uf As UserForm, ByVal WaitMsg As String)
Const TRANSPARENT = 1&
Dim X1 As Long, Y1 As Long
Dim X2 As Long, Y2 As Long
Dim X3 As Long, Y3 As Long
Dim W1 As Long, W2 As Long, W3 As Long
Dim H1 As Long, H2 As Long, H3 As Long
Dim IFont As stdole.IFont
Dim tFrameRect As RECT
sWaitMsg1 = Split(WaitMsg, vbLf)(0&)
sWaitMsg2 = Split(WaitMsg, vbLf)(1&)
Call IUnknown_GetWindow(Uf.Frame1, VarPtr(hFrame))
Call GetClientRect(hFrame, tFrameRect)
hDC = GetDC(hFrame)
lOldBKMode = SetBkMode(hDC, TRANSPARENT)
Set IFont = Uf.btnExportToSheet.Font
IFont.Size = 16&
hOldFont = SelectObject(hDC, IFont.hFont)
IFont.Size = 10&
Call GetTextExtentPoint32(hDC, sWaitMsg1, Len(sWaitMsg1), tTextSize1)
Call GetTextExtentPoint32(hDC, sWaitMsg2, Len(sWaitMsg2), tTextSize2)
Call GetTextExtentPoint32(hDC, vbNullChar, Len(vbNullChar), tTextSize3)
Call SetTextColor(hDC, vbRed)
W1 = tTextSize1.cx: W2 = tTextSize2.cx: W3 = tTextSize3.cx
H1 = tTextSize1.cy: H2 = tTextSize2.cy: H3 = tTextSize3.cy
X1 = ((tFrameRect.Right - tFrameRect.Left) - W1) / 2&
Y1 = ((tFrameRect.Bottom - tFrameRect.Top) - H1) / 3&
Call SetRect(tTextRect1, X1, Y1, W1 + X1, H1 + Y1)
X2 = ((tFrameRect.Right - tFrameRect.Left) - W2) / 2&
Y2 = Y1 + H1
Call SetRect(tTextRect2, X2, Y2, W2 + X2, H2 + Y2)
X3 = W2 + X2
Call SetRect(tTextRect3, X3, Y2, W3 + X3, H3 + Y2)
bExportingFinished = False
Call KillTimer(Application.hwnd, NULL_PTR)
bErrorFlag = True
Call TimerProc
Call SetTimer(Application.hwnd, NULL_PTR, 500&, AddressOf TimerProc)
End Sub
' ______________________________________ PRIVATE SUBS _______________________________________________
Private Function InterFacesFromClass(tClass As INTERFACE_INFO) As INTERFACE_INFO()
Const S_OK = 0&, CC_STDCALL = 4&, MEMBERID_NIL = -1&
Dim pRefType As LongPtr, pClasstypeInfo As LongPtr, farPtr As LongPtr, psGUID As LongPtr
Dim tTYPEATTR As TYPEATTR, tInterfaceInfo As INTERFACE_INFO
Dim i As Long, lRet As Long, lInterfaceCount As Long
Dim sInterfaceName As String, pImplTypeFlags As Long
lInterfaceCount = tClass.InterfacesCount
ReDim ar(lInterfaceCount - 1&) As INTERFACE_INFO
With tClass
For i = 0& To .InterfacesCount - 1&
lRet = vtblCall(.Ptr, 8& * PTR_LEN, vbLong, CC_STDCALL, i, VarPtr(pRefType)) 'ITypeInfo::GetRefTypeOfImplType
If lRet <> S_OK Then
MsgBox "Unable to retrieve the type description of the implemented interface type.": Exit Function
End If
lRet = vtblCall(.Ptr, 9& * PTR_LEN, vbLong, CC_STDCALL, i, VarPtr(pImplTypeFlags)) 'ITypeInfo::GetImplTypeFlags
lRet = vtblCall(.Ptr, 14& * PTR_LEN, vbLong, CC_STDCALL, pRefType, VarPtr(pClasstypeInfo)) 'ITypeInfo::GetRefTypeInfo
If lRet <> S_OK Then
MsgBox "Unable to retrieve the referenced type descriptions.": Exit Function
End If
lRet = vtblCall(pClasstypeInfo, 12& * PTR_LEN, vbLong, CC_STDCALL, MEMBERID_NIL, VarPtr(sInterfaceName), NULL_PTR, NULL_PTR, NULL_PTR) 'ITypeInfo::GetDocumentation
If lRet <> S_OK Then
MsgBox "Unable to retrieve the documentation string.": Exit Function
End If
lRet = vtblCall(pClasstypeInfo, 3& * PTR_LEN, vbLong, CC_STDCALL, VarPtr(farPtr)) 'ITypeInfo::GetTypeAttr
If lRet <> S_OK Then
MsgBox "Unable to retrieve a TYPEATTR structure that contains the attributes of the type description"
Exit Function
End If
Call CopyMemory(tTYPEATTR, ByVal farPtr, LenB(tTYPEATTR))
lRet = vtblCall(pClasstypeInfo, 19& * PTR_LEN, vbEmpty, CC_STDCALL, farPtr) 'ITypeInfo::ReleaseTypeAttr
Call StringFromIID(tTYPEATTR.aGUID, VarPtr(psGUID))
With tInterfaceInfo
.Ptr = pClasstypeInfo
.GUID = GetStrFromPtrW(psGUID)
.Name = sInterfaceName
.MembersCount = tTYPEATTR.cFuncs
.wMajorVerNum = tTYPEATTR.wMajorVerNum
.wMinorVerNum = tTYPEATTR.wMinorVerNum
.IMPLTYPEFLAGS = pImplTypeFlags
End With
ar(i) = tInterfaceInfo
Next i
End With
InterFacesFromClass = ar
End Function
Private Function vtblCall( _
ByVal InterfacePointer As LongPtr, _
ByVal VTableOffset As Long, _
ByVal FunctionReturnType As Long, _
ByVal CallConvention As Long, _
ParamArray FunctionParameters() As Variant _
) As Variant
Dim vParamPtr() As LongPtr
If InterfacePointer = 0& Or VTableOffset < 0& Then Exit Function
If Not (FunctionReturnType And &HFFFF0000) = 0& Then Exit Function
Dim pIndex As Long, pCount As Long
Dim vParamType() As Integer
Dim vRtn As Variant, vParams() As Variant
vParams() = FunctionParameters()
pCount = Abs(UBound(vParams) - LBound(vParams) + 1&)
If pCount = 0& Then
ReDim vParamPtr(0& To 0&)
ReDim vParamType(0& To 0&)
Else
ReDim vParamPtr(0& To pCount - 1&)
ReDim vParamType(0& To pCount - 1&)
For pIndex = 0& To pCount - 1&
vParamPtr(pIndex) = VarPtr(vParams(pIndex))
vParamType(pIndex) = VarType(vParams(pIndex))
Next
End If
pIndex = DispCallFunc(InterfacePointer, VTableOffset, CallConvention, FunctionReturnType, pCount, vParamType(0&), vParamPtr(0&), vRtn)
If pIndex = 0& Then
vtblCall = vRtn
Else
SetLastError pIndex
End If
End Function
Private Function MemberKindToStandardMemberName( _
ByVal MembKind As String, _
ByVal ReturnType As String _
) As String
Select Case MembKind
Case Is = "VbLet", "VbGet", "VbSet"
MemberKindToStandardMemberName = "Property"
Case "VbMethod"
If ReturnType = "VOID" Or ReturnType = "HRESULT" Then
MemberKindToStandardMemberName = "Sub"
Else
MemberKindToStandardMemberName = "Function"
End If
Case "VbMethod [Event]"
MemberKindToStandardMemberName = "Event"
End Select
End Function
Private Function BuildClassInfoString(INFO As INTERFACE_INFO, bShowUnkDisp As Boolean) As TEXT_STRUCT
Dim tString As TEXT_STRUCT
With tString
.Caption = _
"[Class Name:] " & vbLf & _
"[Members Count:] " & vbLf & _
"[GUID:] " & vbLf & _
"[LCID:] " & vbLf & _
"[PTR:] "
.Value = INFO.Name & vbLf & _
IIf(bShowUnkDisp, INFO.MembersCount, INFO.MembersCount - 7&) & vbLf & _
INFO.GUID & vbLf & _
INFO.LCID & vbLf & _
INFO.InterfacesCount
End With
BuildClassInfoString = tString
End Function
Private Function ReturnType(ByVal RetType As VarEnum) As String
Dim sRetVarType As String
Select Case RetType
Case VT_NULL: sRetVarType = "Long"
Case VT_I2: sRetVarType = "Integer"
Case VT_I4: sRetVarType = "Long"
Case VT_R4: sRetVarType = "Single"
Case VT_R8: sRetVarType = "Double"
Case VT_CY: sRetVarType = "Currency"
Case VT_DATE: sRetVarType = "Date"
Case VT_BSTR: sRetVarType = "BSTR(String)"
Case VT_DISPATCH, VT_PTR: sRetVarType = "Object"
Case VT_ERROR: sRetVarType = "SCODE"
Case VT_BOOL: sRetVarType = "Boolean"
Case VT_VARIANT: sRetVarType = "VARIANT"
Case VT_UNKNOWN: sRetVarType = "IUnknown*"
Case VT_UI1: sRetVarType = "Byte"
Case VT_DECIMAL: sRetVarType = "Decimal"
Case VT_I1: sRetVarType = "Char"
Case VT_UI2: sRetVarType = "USHORT"
Case VT_UI4: sRetVarType = "ULONG"
Case VT_I8: sRetVarType = "LongLong"
Case VT_UI8: sRetVarType = "unsigned __int64"
Case VT_INT: sRetVarType = "int"
Case VT_UINT: sRetVarType = "UINT"
Case VT_HRESULT: sRetVarType = "HRESULT"
Case VT_VOID: sRetVarType = "VOID"
Case VT_LPSTR: sRetVarType = "char*"
Case VT_LPWSTR: sRetVarType = "wchar_t*"
Case Else: sRetVarType = "ANY"
End Select
ReturnType = sRetVarType
End Function
Private Function GetStrFromPtrW(ByVal lpString As LongPtr) As String
Call SysReAllocString(VarPtr(GetStrFromPtrW), lpString)
Call CoTaskMemFree(lpString)
End Function
Private Function ModuleFileName(ByVal ModuleName As String) As String
Const MAX_PATH = 1024&
Dim sBuffer As String, lRet As Long, hMod As LongPtr
hMod = GetModuleHandleW(StrPtr(ModuleName))
sBuffer = Space(MAX_PATH)
lRet = GetModuleFileNameW(hMod, StrPtr(sBuffer), Len(sBuffer))
ModuleFileName = Left(sBuffer, lRet)
End Function
Private Sub FormatExportSheet(ByVal Sh As Worksheet)
Dim oRange As Range
With Sh
With .Range("A1:J1")
.Cells(1) = "TLB": .Cells(2) = "ClassName"
.Cells(3) = "Member": .Cells(4) = "MemberKind"
.Cells(5) = "InvKind\Val": .Cells(6) = "RetType"
.Cells(7) = "ParamCount": .Cells(8) = "OptParamCount"
.Cells(9) = "VTblOffset": .Cells(10) = "DispID"
.Interior.Color = &HEED7BD
.Font.Bold = True
.Font.Color = vbBlue
.Font.Size = 14&
.Borders.LineStyle = xlContinuous
.Columns("B:I").EntireColumn.AutoFit
.Columns("D:J").EntireColumn.HorizontalAlignment = xlCenter
.Range("a2").HorizontalAlignment = xlLeft
.Cells(1).Offset(2).Select
ActiveWindow.FreezePanes = True
ActiveWindow.Zoom = 90&
End With
Set oRange = .Range("B5:B" & .Range("B" & .UsedRange.Rows.Count).End(xlUp).Row)
Set oRange = oRange.SpecialCells(xlCellTypeBlanks)
Dim oArea As Variant
For Each oArea In oRange.Areas
oArea.Rows.Group
Next
.Outline.ShowLevels RowLevels:=2&
End With
bExportingFinished = True
MsgBox "Done exporting the TypeLib to the worksheet.", vbInformation
End Sub
Private Sub Release_DC()
Call SelectObject(hDC, lOldBKMode)
Call SelectObject(hDC, hOldFont)
Call ReleaseDC(hFrame, hDC)
End Sub
Private Sub TimerProc()
Const DT_CENTER = &H1
Static i As Long
If bErrorFlag = False Then
Call KillTimer(Application.hwnd, NULL_PTR)
Exit Sub
End If
Call DrawText(hDC, StrPtr(sWaitMsg1), -1&, tTextRect1, DT_CENTER)
Call DrawText(hDC, StrPtr(sWaitMsg2), -1&, tTextRect2, DT_CENTER)
If i Mod 2& Then
Call DrawText(hDC, StrPtr(" " & ChrW(&H25A0)), -1&, tTextRect3, DT_CENTER)
Else
Call InvalidateRect(hFrame, tTextRect3, 0&)
End If
If bExportingFinished Then
bExportingFinished = False: bErrorFlag = False: i = 0&
Call KillTimer(Application.hwnd, NULL_PTR)
Call InvalidateRect(hFrame, tTextRect1, 0&)
Call InvalidateRect(hFrame, tTextRect2, 0&)
Call InvalidateRect(hFrame, tTextRect3, 0&)
Call Release_DC
End If
i = i + 1&
End Sub