Skip to content

Instantly share code, notes, and snippets.

@TLMcode
Last active December 31, 2019 06:34
Show Gist options
  • Save TLMcode/af02957c667b0b227ef649670ad19159 to your computer and use it in GitHub Desktop.
Save TLMcode/af02957c667b0b227ef649670ad19159 to your computer and use it in GitHub Desktop.
Enumerate COM Object Members
;;
;; iTypeInfo - Enum Com Members - By jethrow
;;
;; small Mod by Blackholyman to output member Name and Doc string in "UTF-16" and put it in a listview
;;
;; GUI & furthers Mods by TLM
;;
Gui, Add, Text,, Enter COM Object
Gui, Add, Edit, vComObject w200, MSXML2.DOMDocument.6.0 ; , % Format( "{:50}", A_Space )
Gui, Add, Button, gSearch Section, Search Members
Gui, Add, Text, vDisp ys5, % Format( "{:190}", A_Space )
Gui, Add, ListView, r20 w700 xs Section, #|ID|Name|Kind|DocString ; Create a ListView.
Loop % LV_GetCount( "Col" )
LV_ModifyCol( A_Index, "AutoHdr" )
Gui, Show,, Enum COM Members
Return
Search:
Gui, Submit, NoHide
Try ( sd := ComObjCreate( ComObject ) )
Catch Err
{
MsgBox, 0x10, Whoops!, % Err.Message "!`nTry a valid object eg: Shell.Explorer"
Return
}
GuiControl, Disable, Search
GuiControl,, Disp, % "Interface: " ComObjType( sd, "Name" )
Loop, Parse, % ( EnumComMembers( GetTypeInfo( sd ) ), LV_Delete() ), `n
{
Fields := StrSplit( A_LoopField, "|" )
LV_Add(, A_Index, Fields[1], Fields[2], Fields[3], Fields[4], Fields[5] )
}
For Each, Column in Fields
LV_ModifyCol( Each, "Auto" )
GuiControl, Enable, Search
Return
GuiClose:
ExitApp
EnumComMembers( pti ) { ; releases ITypeInfo Interface
static InvKind := {1:"[method]", 2:"[get]", 4:"[put]", 8:"[putref]"}
{ ; Com Methods
GetTypeAttr := vTable(pti, 3)
ReleaseTypeAttr := vTable(pti, 19)
GetRefTypeOfImplType := vTable(pti, 8)
GetRefTypeInfo := vTable(pti, 14)
GetFuncDesc := vTable(pti, 5)
ReleaseFuncDesc := vTable(pti, 20)
GetDocumentation := vTable(pti, 12)
}
{ ; get cFuncs (number of functions)
DllCall( GetTypeAttr, "ptr", pti, "ptr*", typeAttr )
cFuncs := NumGet( typeAttr+0, 40+A_PtrSize, "short" )
cImplTypes := NumGet( typeAttr+0, 44+A_PtrSize, "short" )
DllCall( ReleaseTypeAttr, "ptr", pti, "ptr", typeAttr )
}
if cImplTypes { ; Get Inherited Class (cImplTypes should be true)
DllCall(GetRefTypeOfImplType, "ptr",pti, "int",0, "int*",pRefType)
DllCall(GetRefTypeInfo, "ptr",pti, "ptr",pRefType, "ptr*", pti2)
DllCall(GetDocumentation, "ptr",pti2, "int",-1, "ptr*",Name, "ptr",0, "ptr",0, "ptr",0) ; get Interface Name
if StrGet(Name) != "IDispatch"
t .= EnumComMembers(pti2) "`n"
else,
ObjRelease(pti2)
}
Loop, %cFuncs% { ; get Member IDs
DllCall(GetFuncDesc, "ptr",pti, "int",A_Index-1, "ptr*",FuncDesc)
ID := NumGet(FuncDesc+0, "short") ; get Member ID
n := NumGet(FuncDesc+0, 4+3*A_PtrSize, "int") ; get InvKind
; Args := NumGet(FuncDesc+0, 12+3*A_PtrSize, "short") ; get Num of Args
; Opt := NumGet(FuncDesc+0, 14+3*A_PtrSize, "short") ; get Num of Opt Args
DllCall(ReleaseFuncDesc, "ptr",pti, "ptr",FuncDesc)
DllCall(GetDocumentation, "ptr",pti, "int",ID, "ptr*",Name, "ptr*",DocString, "ptr",0, "ptr",0)
;~ msgbox % StrGet(DocString, "UTF-16")
if StrGet(Name, "UTF-16") ; Exclude Members that didn't Return a Name
t .= ID "|" StrGet(Name, "UTF-16") "|" InvKind[n] "|" StrGet(DocString, "UTF-16") "`n"
}
{ ; formatting & cleanup
t := SubStr(t,1,-1)
Sort, t, ND`n
ObjRelease(pti)
}
Return, t
}
GetTypeInfo( ptr )
{
if ComObjType( ptr ) = 9
ptr := ComObjValue( ptr )
; Check if *ptr* has ITypeInfo Interface
GetTypeInfoCount := vtable( ptr, 3 )
DllCall( GetTypeInfoCount, "ptr",ptr, "ptr*",HasITypeInfo )
if Not HasITypeInfo
{
MsgBox ITypeInfo Interface not supported
Exit
}
GetTypeInfo := vTable( ptr, 4 )
if DllCall( GetTypeInfo, "ptr",ptr, "uint",0, "uint",0, "ptr*", pti ) = 0
Return, pti
}
vTable( ptr, n ) { ; see ComObjQuery documentation
Return NumGet(NumGet(ptr+0), n*A_PtrSize)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment