#include-once ; #FUNCTION# ============================================================================= ; Name...........: __ObjectFromTag ; @trancexx ; ======================================================================================== Func __ObjectFromTag($sFunctionPrefix, $tagInterface, ByRef $tInterface, $tag_Property = '', $bIsUnknown = Default, $sIID = Default, $fPrint = False) ; last param is IID_IUnknown by default $sIID = ((($sIID = Default) Or ($sIID = True) Or ($sIID = '')) ? '{00000000-0000-0000-C000-000000000046}' : $sIID) ;<<== $sIID_IUNKNOWN $bIsUnknown = ((($bIsUnknown = Default) Or ($bIsUnknown = True) Or ($bIsUnknown = 1)) ? True : False) Local $sInterface = $tagInterface ; copy interface description Local $tagIUnknown = "QueryInterface hresult(ptr;ptr*);" & _ "AddRef dword();" & _ "Release dword();" ; Adding IUnknown methods If $bIsUnknown Then $tagInterface = $tagIUnknown & $tagInterface ; Below line is really simple even though it looks super complex. It's just written weird to fit in one line, not to steal your attention Local $aMethods = StringSplit(StringReplace(StringReplace(StringReplace(StringReplace(StringTrimRight(StringReplace(StringRegExpReplace(StringRegExpReplace($tagInterface, "\w+\*", "ptr"), "\h*(\w+)\h*(\w+\*?)\h*(\((.*?)\))\h*(;|;*\z)", "$1\|$2;$4" & @LF), ";" & @LF, @LF), 1), ";object", ";idispatch"), "hresult", "long"), "bstr", "ptr"), "variant", "ptr"), @LF, 3) Local $iUbound = UBound($aMethods) Local $sMethod, $aSplit, $sNamePart, $aTagPart, $sTagPart, $sRet, $sParams, $hCallback $tag_Property = StringStripWS($tag_Property, 1) If $tag_Property <> '' Then $tag_Property = 'align 1;' & ((StringRight($tag_Property, 1) <> ';') ? $tag_Property & ';' : $tag_Property) ; Allocation Local $tagGS = "char strDataGS[%i];" & $tag_Property & "ptr vtableGS;int LengthGS;" Local $tagExtra = $tagGS & "char sIID[" & StringLen("{00000000-0000-0000-C000-000000000046}") + 1 & "];" Local $tagIINTERFACE = $tagExtra & "int RefCount;int Size;ptr Object;ptr Methods[%i];int_ptr Callbacks[%i];ulong_ptr Slots[16]" $tInterface = DllStructCreate(StringFormat($tagIINTERFACE, StringLen($tag_Property) + 1, $iUbound, $iUbound)); 16 pointer sized elements more to create space for possible private props If @error Then Return SetError(1, 0, 0) For $i = 0 To $iUbound - 1 $aSplit = StringSplit($aMethods[$i], "|", 2) If UBound($aSplit) <> 2 Then ReDim $aSplit[2] $sNamePart = $aSplit[0] $sTagPart = $aSplit[1] $sMethod = $sFunctionPrefix & $sNamePart ; ConsoleWrite("$sMethod: " & $sMethod & @CRLF) If $fPrint Then Local $iPar = StringInStr($sTagPart, ";", 2), $t If $iPar Then $t = "Ret: " & StringLeft($sTagPart, $iPar - 1) & " " & _ "Par: " & StringRight($sTagPart, StringLen($sTagPart) - $iPar) Else $t = "Ret: " & $sTagPart EndIf Local $s = "Func " & $sMethod & _ "( $pSelf ) ; " & $t & @CRLF & _ "EndFunc" & @CRLF ConsoleWrite($s) EndIf $aTagPart = StringSplit($sTagPart, ";", 2) $sRet = $aTagPart[0] $sParams = StringReplace($sTagPart, $sRet, "", 1) $sParams = "ptr" & $sParams $hCallback = DllCallbackRegister($sMethod, $sRet, $sParams) If @error Then ConsoleWrite('! ' & @error & ' ' & $sMethod & @CRLF & @CRLF) EndIf DllStructSetData($tInterface, "Methods", DllCallbackGetPtr($hCallback), $i + 1) ; save callback pointer DllStructSetData($tInterface, "Callbacks", $hCallback, $i + 1) ; save callback handle Next DllStructSetData($tInterface, "RefCount", 1) ; initial ref count is 1 DllStructSetData($tInterface, "Size", $iUbound) ; number of interface methods DllStructSetData($tInterface, "Object", DllStructGetPtr($tInterface, "Methods")) ; Interface method pointers DllStructSetData($tInterface, "sIID", $sIID) DllStructSetData($tInterface, "LengthGS", StringLen($tag_Property) + 1) DllStructSetData($tInterface, "strDataGS", $tag_Property) $tInterface.vtableGS = DllStructGetPtr($tInterface, "strDataGS") Return ObjCreateInterface(DllStructGetPtr($tInterface, "Object"), $sIID, $sInterface, $bIsUnknown) ; pointer that's wrapped into object EndFunc ;==>ObjectFromTag ; #FUNCTION# ============================================================================= ; Name...........: __DeleteObjectFromTag ; @trancexx ; ======================================================================================== Func __DeleteObjectFromTag( ByRef $tInterface ) For $i = 1 To DllStructGetData( $tInterface, "Size" ) DllCallbackFree( DllStructGetData( $tInterface, "Callbacks", $i ) ) Next $tInterface = 0 EndFunc ; #FUNCTION# ============================================================================= ; Name...........: __QueryInterface ; ======================================================================================== Func __QueryInterface($pSelf, $pRIID, $pObj) If Not $pObj Then Return 0x80004003 ;<<== $E_POINTER Local $sIID = __StringFromGUID($pRIID) Local $iIID = DllStructGetData(DllStructCreate("char[" & StringLen("{00000000-0000-0000-C000-000000000046}") + 1 & "]", $pSelf - (4 + 4 + 39)), 1) If $sIID = "{00000000-0000-0000-C000-000000000046}" Or $sIID = $iIID Then DllStructSetData(DllStructCreate("ptr", $pObj), 1, $pSelf) __AddRef($pSelf) Return 0x00000000 ;<<==$S_OK EndIf Return 0x80004002 ;<== $E_NOINTERFACE EndFunc ;==>_QueryInterface ; #FUNCTION# ============================================================================= ; Name...........: __AddRef ; ======================================================================================== Func __AddRef($pSelf) Local $tRef = DllStructCreate("int", $pSelf - (4 + 4)) ; reference counter is size of two ints before Local $iRef = DllStructGetData($tRef, 1) + 1 ; increment DllStructSetData($tRef, 1, $iRef) Return $iRef EndFunc ;==>_AddRef ; #FUNCTION# ============================================================================= ; Name...........: __Release ; ======================================================================================== Func __Release($pSelf) Local $tRef = DllStructCreate("int", $pSelf - (4 + 4)) ; reference counter is size of two ints before Local $iRef = DllStructGetData($tRef, 1) - 1 ; decrement DllStructSetData($tRef, 1, $iRef) Return $iRef EndFunc ;==>_Release ; #FUNCTION# ============================================================================= ; Name...........: __StringFromGUID ; ======================================================================================== Func __StringFromGUID($pGUID) Local $aResult = DllCall("ole32.dll", "int", "StringFromGUID2", "struct*", $pGUID, "wstr", "", "int", 40) If @error Then Return SetError(@error, @extended, "") Return SetExtended($aResult[0], $aResult[2]) EndFunc ; #FUNCTION# ============================================================================= ; Name...........: __SetProperty ; @jugador ; ======================================================================================== Func __SetProperty($oSelf, $iName, $vData) If Not IsObj($oSelf) AND Not IsPtr($oSelf) Then Return Local $pSelf = ((IsObj($oSelf)) ? ptr($oSelf()) : $oSelf) Local $tSize = DllStructCreate("int", $pSelf - ((4 + 4 + 39) + 4)) If DllStructGetData($tSize, 1) < 2 Then Return Local $p_vtableGS = ptr($pSelf - ((4 + 4 + 39) + (4 + 4))) Local $tStringPtr = DllStructCreate("ptr", $p_vtableGS) Local $tString = DllStructCreate(StringFormat("char[%i]", DllStructGetData($tSize, 1)), DllStructGetData($tStringPtr, 1)) Local $sString = DllStructGetData($tString, 1) Local $sRegex = '(.*?)([^|;]*\b' & $iName & '\b.*?;)' Local $aMatch = StringRegExp($sString, $sRegex, 3) If Not IsArray($aMatch) Then Return Local $p_toFirst_Element = $p_vtableGS - (DllStructGetSize(DllStructCreate(StringTrimRight($sString, 1)))) Local $tProperty = DllStructCreate(StringTrimRight($sString, 1), $p_toFirst_Element) DllStructSetData($tProperty, $iName, $vData) Return EndFunc ;==>__SetProperty ; #FUNCTION# ============================================================================= ; Name...........: __GetProperty ; @jugador ; ======================================================================================== Func __GetProperty(ByRef $oSelf, $iName) If Not IsObj($oSelf) AND Not IsPtr($oSelf) Then Return Local $pSelf = ((IsObj($oSelf)) ? ptr($oSelf()) : $oSelf) Local $tSize = DllStructCreate("int", $pSelf - ((4 + 4 + 39) + 4)) If DllStructGetData($tSize, 1) < 2 Then Return Local $p_vtableGS = ptr($pSelf - ((4 + 4 + 39) + (4 + 4))) Local $tStringPtr = DllStructCreate("ptr", $p_vtableGS) Local $tString = DllStructCreate(StringFormat("char[%i]", DllStructGetData($tSize, 1)), DllStructGetData($tStringPtr, 1)) Local $sString = DllStructGetData($tString, 1) Local $sRegex = '(.*?)([^|;]*\b' & $iName & '\b.*?;)' Local $aMatch = StringRegExp($sString, $sRegex, 3) If Not IsArray($aMatch) Then Return Local $p_toFirst_Element = $p_vtableGS - (DllStructGetSize(DllStructCreate(StringTrimRight($sString, 1)))) Local $tProperty = DllStructCreate(StringTrimRight($sString, 1), $p_toFirst_Element) Return DllStructGetData($tProperty, $iName) EndFunc ;==>__GetProperty