ComObj iTypInfo (jethrow, Lexikos, SKAN, Maul-Esel...)

Get help with using AutoHotkey and its commands and hotkeys
Bluesmaster
Posts: 1
Joined: 22 Mar 2016, 11:00

ComObj iTypInfo (jethrow, Lexikos, SKAN, Maul-Esel...)

22 Mar 2016, 11:38

Hello, building on jethrows: https://autohotkey.com/board/topic/7103 ... ntry450288
I want to add the COM-functions return Value and input arguments

Idea: ElemDescFunc > tdesc > hreftype > GetRefTypeInfo > GetDocumentation

Problem: hreftype and its processing (line 57)

Code: Select all

;~ sd := ComObjCreate("Shell.Explorer")
comViewer( comObj := ComObjCreate("Excel.Application") )
comViewer( comObj ){

	; 1 - GUI
	Gui,  +AlwaysOnTop
	Gui, Add, ListView, r20 w1000 h900  Grid  NoSortHdr  -ReadOnly, Name|Debug|InvKind
	LV_ModifyCol( 1 , 150 )
	LV_ModifyCol( 2 , 650 )
	LV_ModifyCol( 3 , 150 )
	Gui Show, w1100 h900


	; 2 - INFO TYPE INTERFACE ADRESS
	if ComObjType(comObj)=9
		comObj := ComObjValue( comObj )
	DllCall( GetTypeInfoCount:=NumGet(NumGet(comObj+0),3*A_PtrSize)    , "ptr", comObj , "ptr*",HasITypeInfo)
	if Not HasITypeInfo    ; Check if *comObj* has ITypeInfo Interface
		MsgBox ITypeInfo Interface not supported
	GetTypeInfo := NumGet(NumGet(comObj+0), 4 *A_PtrSize)
	DllCall( GetTypeInfo , "ptr", comObj , "uint",0, "uint",0, "ptr*", pti )


	; 3 - VTABLE SHORTS
	static InvKind := {1:"[method]", 2:"[get]", 4:"[put]", 8:"[putref]"}
	GetTypeAttr 		 := NumGet(NumGet(pti+0),  3 *A_PtrSize)
	ReleaseTypeAttr		 := NumGet(NumGet(pti+0), 19 *A_PtrSize)
	GetRefTypeOfImplType := NumGet(NumGet(pti+0),  8 *A_PtrSize)
	GetRefTypeInfo 		 := NumGet(NumGet(pti+0), 14 *A_PtrSize)
	GetFuncDesc 		 := NumGet(NumGet(pti+0),  5 *A_PtrSize)
	ReleaseFuncDesc 	 := NumGet(NumGet(pti+0), 20 *A_PtrSize)
	GetDocumentation 	 := NumGet(NumGet(pti+0), 12 *A_PtrSize)


	; 4 - GET MEMBERS
	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)
	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
		ElemDescFunc := NumGet(FuncDesc+0, 44 , "Ptr" )  ;  (ELEMDESC)
			tdesc    := NumGet( ElemDescFunc , 0 , "Ptr" )   ;  (TYPEDESC)
			  ;~ TYPEDESC
				  ;~ struct tagTYPEDESC  *lptdesc;  4/8         0
				  ;~ struct tagARRAYDESC *lpadesc;  4/8      4/ 8
				  ;~ HREFTYPE hreftype;             4        8/16
				  ;~ VARTYPE vt;                    4       12/20
				hreftype := NumGet( tdesc , 16 , "PTR"  )
				vt   	 := NumGet( tdesc , 20 , "UShort")   ;   =  (VARTYPE)  > noch fehlerhaft ... typ?

		; !!!!!!!!!!!!!   PROBLEM-SECTOR  how to receive name for "hreftype"
		DllCall( GetRefTypeInfo    ,"ptr", pti     , "PTR" , hreftype          ,  "ptr*" , ptrRTI  ) 				                 	 ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms221211(v=vs.85).aspx		
		DllCall( GetDocumentation  ,"ptr",  ptrRTI  , "Int"  , noMemberID := -1  ,  "ptr*"  , funReturnValueTypeName ,   "ptr*",0,"UInt*",0,"ptr*",0)	 ; https://msdn.microsoft.com/de-de/library/windows/desktop/ms221227(v=vs.85).aspx
		funReturnValueTypeName  := StrGet(funReturnValueTypeName ) 
		; !!!!!!!!!!!!!   PROBLEM-SECTOR  how to receive name for "hreftype"
	

		DllCall( GetDocumentation , "ptr" , pti , "int" , ID ,"ptr*",Name     ,"ptr",0,"ptr",0,"ptr",0)  ; 
		if StrGet(Name) ; Exclude Members that didn't return a Name
			LV_Add("", StrGet( Name ) ,  "varType:" . vt . " - hreftype: " . hreftype . " -  RTI: " . ptrRTI  . " - TypeName: " . funReturnValueTypeName   , InvKind[ n ] , n )
	}
	
} 

Deep knowledge of COM and Dllcall is needed (which I am lacking). Maul-Esel has done it successfully in "importTypLib".
But after 2 days of reading all com-related code in the forum I really need help.
Is this even possible from an instance? Or do I have to load the typlib as Maul-Esel did? A million questions, but lets first start the discussion...

Thank you so much guys
lexikos
Posts: 6668
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: ComObj iTypInfo (jethrow, Lexikos, SKAN, Maul-Esel...)

22 Mar 2016, 17:13

I think it's not deep knowledge of COM that you need so much as a better understanding of how structs work.
ElemDescFunc := NumGet(FuncDesc+0, 44 , "Ptr" )
Is that calculated for 64-bit? If so, you should mention that you are testing on 64-bit. An offset calculated for 64-bit won't necessarily work for 32-bit.

If Opt (presumably cParamsOpt) is at offset 14+3*A_PtrSize, then in theory, elemdescFunc is at offset 14+3*A_PtrSize + sizeof(cParamsOpt) + sizeof(oVft) + sizeof(cScodes). However, it is slightly different because of data alignment: the ELEMDESC struct contains pointers, so must be aligned to a pointer boundary (offset must be a multiple of A_PtrSize). Effectively you can calculate the offset as if oVft and cScodes are one pointer instead of 4 bytes: 16+4*A_PtrSize

However, elemdescFunc is not a pointer, but a struct which is nested inside the FUNCDESC struct directly. So ElemDescFunc := FuncDesc+16+4*A_PtrSize (and then use ElemDescFunc+0 with NumGet). Again, the tdesc field is a struct which is nested directly in the ELEMDESC struct; since it's the first member, both have exactly the same address: tdesc := ElemDescFunc.

For TYPEDESC, the first three members are in a union. This means that each member directly in the union starts at exactly the same address - they overlap. hreftype is at offset 0 of TYPEDESC and vt is at offset A_PtrSize. You've noted that hreftype is 4 bytes, which is correct (contrary to most "handle" types, since it's really just a DWORD), but you've used "PTR". This will also retrieve the 4 bytes following hreftype, which will contain meaningless data (it might work anyway depending on the value of this "garbage" and whether you truncate it later on).

hreftype is only meaningful when vt is VT_USER_DEFINED, which is for returning custom structs. In most cases you just get vt, which tells you exactly which integral type it is.

When someone returns a BSTR to you, you need to free it afterward by calling SysFreeString. Also, StrGet(bstr) will only work on Unicode builds; you should use StrGet(bstr, "UTF-16").

On your GUI, you've specified h900 for the control and h900 for the GUI, but there is also a margin above the control, so the control is clipped. In this case I'd just omit the height from the GUI and let it be calculated automatically.

If you specify both r20 and h900 for a control's height, only one will take effect.

(900 is too high on my 1080p screen with 125% scaling.)

Return to “Ask For Help”

Who is online

Users browsing this forum: au6, Bing [Bot], BushMange, CEA6597, Google [Bot], howardb1, VACO BenQ, w0z and 198 guests