#include-once OnAutoItExitRegister("__GetRef_OnAutoItExit") Global $__GDist = ObjCreate("Scripting.Dictionary") Global $s_IDispatch[1] ; #FUNCTION# ============================================================================= ; Name ..........: __GetRef ; Syntax ........: __GetRef($o_FunName = '', Const $p1 = Default, Const $p2 = Default, Const $p3 = Default, Const $p4 = Default, _ ; Const $p5 = Default, Const $p6 = Default) ; Parameters ....: $o_FunName - Callbacks Function Name ; $p1 - [optional] ; $p2 - [optional] ; $p3 - [optional] ; $p4 - [optional] ; $p5 - [optional] ; $p6 - [optional] ; Return values .: Object ; Author ........: jugador ; ======================================================================================== Func __GetRef($o_FunName = '', Const $p1 = Default, Const $p2 = Default, Const $p3 = Default, _ Const $p4 = Default, Const $p5 = Default, Const $p6 = Default) If Not IsString($o_FunName) Then Return Local $oComErr = Null $oComErr = ObjEvent("AutoIt.Error", __GetRef_com_error_handler) #forceref $oComErr Local Const $sIID_IDispatch = "{00020400-0000-0000-C000-000000000046}" Local Const $tagIDispatch = _ "GetTypeInfoCount hresult(dword*);" & _ "GetTypeInfo hresult(dword;dword;ptr*);" & _ "GetIDsOfNames hresult(struct*;struct*;dword;dword;struct*);" & _ "Invoke hresult(uint;struct*;dword;word;struct*;struct*;ptr;uint*);" Local Static $o_Flag = False Local Static $o_Count = 0 If ($o_flag = False) And ($o_FunName <> '') Then $o_Flag = True If ($o_flag = True) And ($o_FunName <> '') Then Local $o_SDObj = ObjCreate("Scripting.Dictionary") Switch @NumParams Case 1 $o_SDObj.Item('Params_1') = $o_FunName Case 2 $o_SDObj.Item('Params_1') = $o_FunName $o_SDObj.Item('Params_2') = $p1 Case 3 $o_SDObj.Item('Params_1') = $o_FunName $o_SDObj.Item('Params_2') = $p1 $o_SDObj.Item('Params_3') = $p2 Case 4 $o_SDObj.Item('Params_1') = $o_FunName $o_SDObj.Item('Params_2') = $p1 $o_SDObj.Item('Params_3') = $p2 $o_SDObj.Item('Params_4') = $p3 Case 5 $o_SDObj.Item('Params_1') = $o_FunName $o_SDObj.Item('Params_2') = $p1 $o_SDObj.Item('Params_3') = $p2 $o_SDObj.Item('Params_4') = $p3 $o_SDObj.Item('Params_5') = $p4 Case 6 $o_SDObj.Item('Params_1') = $o_FunName $o_SDObj.Item('Params_2') = $p1 $o_SDObj.Item('Params_3') = $p2 $o_SDObj.Item('Params_4') = $p3 $o_SDObj.Item('Params_5') = $p4 $o_SDObj.Item('Params_6') = $p5 Case Else $o_SDObj.Item('Params_1') = $o_FunName $o_SDObj.Item('Params_2') = $p1 $o_SDObj.Item('Params_3') = $p2 $o_SDObj.Item('Params_4') = $p3 $o_SDObj.Item('Params_5') = $p4 $o_SDObj.Item('Params_6') = $p5 $o_SDObj.Item('Params_7') = $p6 EndSwitch Local $o_DKey = 'pIDispatch_' & $o_Count Local $o_IKey = 'pInvoke_' & $o_Count $__GDist.Item($o_DKey) = __ObjectFromTag("__GetRef_Interface_", $tagIDispatch, $s_IDispatch[$o_Count]) If Not IsObj($__GDist($o_DKey)) Then __GetRef_ONExit('__ObjectFromTag() Failed', True) Local $o_IDispatch = $__GDist($o_DKey) $__GDist.Item($o_IKey) = ObjCreateInterface($o_IDispatch(), $sIID_IDispatch) If Not IsObj($__GDist($o_IKey)) Then __GetRef_ONExit('ObjCreateInterface(Invoke) Failed', True) Local $o_NKey = String(ptr($__GDist($o_IKey))) $__GDist.Item($o_NKey) = $o_SDObj ReDim $s_IDispatch[UBound($s_IDispatch) + 1] $o_Count += 1 Return $__GDist($o_IKey) Endif If ($o_flag = True) And ($o_FunName = '') Then __GetRef_ONExit('', True) EndFunc ; #FUNCTION# ============================================================================= ; Name...........: __GetRef_OnAutoItExit ; ======================================================================================== Func __GetRef_OnAutoItExit() __GetRef_ONExit('', True) EndFunc ; #FUNCTION# ============================================================================= ; Name...........: __GetRef_ONExit ; ======================================================================================== Func __GetRef_ONExit($o_Msg = '', $o_Exit = False) If Not IsObj($__GDist) Then Return Local $o_SDitem = $__GDist.Count Local $o_Loop = $o_SDitem / 3 ;~ ptr key list Local $o_PtrkeyList = '' For $vKey In $__GDist If StringRegExp($vKey, '(?s)0x\w{8,}', 0) Then $o_PtrkeyList &= $vKey & '|' Next $o_PtrkeyList = StringTrimRight($o_PtrkeyList, 1) $o_PtrkeyList = StringSplit($o_PtrkeyList, '|', 2) For $i = 0 To $o_Loop - 1 If $__GDist.Exists('pInvoke_' & $i) Then $__GDist.Item('pInvoke_' & $i) = 0 EndIf If $__GDist.Exists('pIDispatch_' & $i) Then $__GDist.Item('pIDispatch_' & $i) = 0 EndIf If $__GDist.Exists($o_PtrkeyList[$i]) Then $__GDist.Item($o_PtrkeyList[$i]) = 0 EndIf If IsDllStruct($s_IDispatch[$i]) Then __DeleteObjectFromTag($s_IDispatch[$i]) Next $s_IDispatch = 0 $__GDist.RemoveAll() $__GDist = 0 If $o_Exit Then Exit EndFunc ; #FUNCTION# ============================================================================= ; Name...........: __ObjectFromTag ; @trancexx ; ======================================================================================== Func __ObjectFromTag($sFunctionPrefix, $tagInterface, ByRef $tInterface, $fPrint = False, $bIsUnknown = Default, $sIID = "{00000000-0000-0000-C000-000000000046}") ; last param is IID_IUnknown by default If $bIsUnknown = Default Then $bIsUnknown = True 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 ; Allocation $tInterface = DllStructCreate("int RefCount;int Size;ptr Object;ptr Methods[" & $iUbound & "];int_ptr Callbacks[" & $iUbound & "];ulong_ptr Slots[16]") ; 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 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 Return ObjCreateInterface(DllStructGetPtr($tInterface, "Object"), $sIID, $sInterface, $bIsUnknown) ; pointer that's wrapped into object EndFunc ; #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...........: __GetRef_com_error_handler ; ======================================================================================== Func __GetRef_com_error_handler($oError) With $oError ConsoleWrite(@CRLF & "COM ERROR DETECTED!" & @CRLF) ConsoleWrite(" Error ScriptLine....... " & .scriptline & @CRLF) ConsoleWrite(" Error Number........... " & "0x" & Hex(.number) & " (" & .number & ")" & @CRLF) ConsoleWrite(" Error WinDescription... " & StringStripWS(.windescription, 2) & @CRLF) ConsoleWrite(" Error RetCode.......... " & "0x" & Hex(Number(.retcode)) & " (" & Number(.retcode) & ")" & @CRLF) ConsoleWrite(" Error Description...... " & StringStripWS(.description, 2) & @CRLF) EndWith EndFunc ; #FUNCTION# ============================================================================= ; Name...........: __GetRef_Interface_QueryInterface ; ======================================================================================== Func __GetRef_Interface_QueryInterface($pSelf, $pRIID, $pObj) Local Const $sIID_IUnknown = "{00000000-0000-0000-C000-000000000046}" Local Const $sIID_IDispatch = "{00020400-0000-0000-C000-000000000046}" Local $sIID = __StringFromGUID2($pRIID) If ($sIID = $sIID_IUnknown) Or ($sIID = $sIID_IDispatch) Then DllStructSetData(DllStructCreate("ptr", $pObj), 1, $pSelf) __GetRef_Interface_AddRef($pSelf) Return 0 ;~ $S_OK = 0x00000000 EndIf Return 0x80004002 ;~ $E_NOINTERFACE EndFunc ; #FUNCTION# ============================================================================= ; Name...........: __GetRef_Interface_AddRef ; ======================================================================================== Func __GetRef_Interface_AddRef($pSelf) Return 1 EndFunc ; #FUNCTION# ============================================================================= ; Name...........: __GetRef_Interface_Release ; ======================================================================================== Func __GetRef_Interface_Release($pSelf) Return 1 EndFunc ; #FUNCTION# ============================================================================= ; Name...........: __GetRef_Interface_GetTypeInfoCount ; ======================================================================================== Func __GetRef_Interface_GetTypeInfoCount( $pSelf, $pctinfo ) Return 0 ; S_OK = 0x00000000 #forceref $pSelf, $pctinfo EndFunc ; #FUNCTION# ============================================================================= ; Name...........: __GetRef_Interface_GetTypeInfo ; ======================================================================================== Func __GetRef_Interface_GetTypeInfo( $pSelf, $iTInfo, $lcid, $ppTInfo ) Return 0 ; S_OK = 0x00000000 #forceref $pSelf, $iTInfo, $lcid, $ppTInfo EndFunc ; #FUNCTION# ============================================================================= ; Name...........: __GetRef_Interface_GetIDsOfNames ; ======================================================================================== Func __GetRef_Interface_GetIDsOfNames( $pSelf, $riid, $rgszNames, $cNames, $lcid, $rgDispId ) Return 0 ; S_OK = 0x00000000 #forceref $pSelf, $riid, $rgszNames, $cNames, $lcid, $rgDispId EndFunc ; #FUNCTION# ============================================================================= ; Name...........: __GetRef_Interface_Invoke ; ======================================================================================== Func __GetRef_Interface_Invoke( $pSelf, $dispIdMember, $riid, $lcid, $wFlags, $pDispParams, $pVarResult, $pExcepInfo, $puArgErr ) If $__GDist.Exists(String($pSelf)) Then Local $o_SDObj = $__GDist(String($pSelf)) If IsObj($o_SDObj) Then Local $o_ResetFlag = False Local $o_ResetHolder[0][2] ;~ key name | value Local $o_NoParams = $o_SDObj.Count Local $o_FunctionName = $o_SDObj('Params_1') Local Const $DISPATCH_METHOD = 0x1 Local Const $DISPATCH_PROPERTYGET = 0x2 Local Const $tVARIANT = 'word vt;word r1;word r2;word r3;ptr data; ptr' Local Const $tagDISPPARAMS = 'ptr rgvarg;ptr rgdispidNamedArgs;uint cArgs;uint cNamedArgs;' Local $t_DispParams = DllStructCreate($tagDISPPARAMS, $pDispParams) Local $o_rgvarg = DllStructCreate($tVARIANT, DllStructGetData($t_DispParams, 1)) Local $I_cArgs = DllStructGetData($t_DispParams, 3) If $I_cArgs >= $o_NoParams Then Return 0 If $I_cArgs > 0 Then If $wFlags = BitOR($DISPATCH_METHOD, $DISPATCH_PROPERTYGET) Then Local $o_GetKey, $o_LastKey Local $o_COMVt_Vlu = '' $o_LastKey = 2 + ($I_cArgs - 1) For $i = 0 To $I_cArgs - 1 $o_GetKey = 'Params_' & $o_LastKey - $i If $o_SDObj.Exists($o_GetKey) Then ReDim $o_ResetHolder[UBound($o_ResetHolder) + 1][2] $o_ResetHolder[$i][0] = $o_GetKey ;~ Store default key $o_ResetHolder[$i][1] = $o_SDObj($o_GetKey) ;~ Store default value $o_COMVt_Vlu = __COMVariantToValue(DllStructGetData($t_DispParams, 1) + ($i * 16)) ;~ i * sizeof(VARIANT) If @error Then Return 0 ;~ __GetRef_ONExit('', True) $o_SDObj.Item($o_GetKey) = $o_COMVt_Vlu EndIf Next $o_ResetFlag = True EndIf EndIf Switch $o_NoParams Case 1 Call($o_FunctionName) Case 2 Call($o_FunctionName, $o_SDObj('Params_2')) Case 3 Call($o_FunctionName, $o_SDObj('Params_2'), $o_SDObj('Params_3')) Case 4 Call($o_FunctionName, $o_SDObj('Params_2'), $o_SDObj('Params_3'), $o_SDObj('Params_4')) Case 5 Call($o_FunctionName, $o_SDObj('Params_2'), $o_SDObj('Params_3'), $o_SDObj('Params_4'), _ $o_SDObj('Params_5')) Case 6 Call($o_FunctionName, $o_SDObj('Params_2'), $o_SDObj('Params_3'), $o_SDObj('Params_4'), _ $o_SDObj('Params_5'), $o_SDObj('Params_6')) Case Else Call($o_FunctionName, $o_SDObj('Params_2'), $o_SDObj('Params_3'), $o_SDObj('Params_4'), _ $o_SDObj('Params_5'), $o_SDObj('Params_6'), $o_SDObj('Params_7')) EndSwitch ;~ Reset to default value If $o_ResetFlag And (UBound($o_ResetHolder) > 0) Then Local $o_TempKey For $i = 0 To UBound($o_ResetHolder) - 1 $o_TempKey = $o_ResetHolder[$i][0] If $o_SDObj.Exists($o_TempKey) Then $o_SDObj.Item($o_TempKey) = $o_ResetHolder[$i][1] EndIf Next EndIf EndIf EndIf Return 0 ; S_OK = 0x00000000 #forceref $pSelf, $dispIdMember, $riid, $lcid, $wFlags, $pDispParams, $pVarResult, $pExcepInfo, $puArgErr EndFunc ; #FUNCTION# ============================================================================= ; Name...........: __COMVariantToValue ; ======================================================================================== Func __COMVariantToValue($pVariant) Local Const $VT_I4 = 3 Local Const $VT_R8 = 5 Local Const $VT_BSTR = 8 Local Const $VT_UI4 = 19 Local Const $VT_I8 = 20 Local Const $tVARIANT = "word vt;word r1;word r2;word r3;ptr data; ptr" Local $t_rgvarg = DllStructCreate($tVARIANT, $pVariant) Local $iVariantType = DllStructGetData($t_rgvarg, "vt") Local $pData = $pVariant + 8 Local $i_Data = Null Switch $iVariantType Case $VT_I4 Local $t_Data = DllStructCreate( "int", $pData ) $i_Data = DllStructGetData( $t_Data, 1 ) Case $VT_R8 Local $t_Data = DllStructCreate( "double", $pData ) $i_Data = DllStructGetData( $t_Data, 1 ) Case $VT_BSTR Local $t_Ptr = DllStructCreate( "ptr", $pData ) Local $p_Ptr = DllStructGetData( $t_Ptr, 1 ) If $p_Ptr = 0x00000000 Then Return '' $i_Data = SysReadString( $p_Ptr ) Case $VT_UI4 Local $t_Data = DllStructCreate( "ptr", $pData ) $i_Data = DllStructGetData( $t_Data, 1 ) Case $VT_I8 Local $t_Data = DllStructCreate( "INT64", $pData ) $i_Data = DllStructGetData( $t_Data, 1 ) Case Else Return SetError(1) EndSwitch Return $i_Data EndFunc ; #FUNCTION# ============================================================================= ; Name...........: __StringFromGUID2 ; ======================================================================================== Func __StringFromGUID2($pGUID) Local $aReturn = DllCall('ole32.dll', 'int', 'StringFromGUID2', 'struct*', $pGUID, 'wstr', '', 'int', 65536) If @error Or Not $aReturn[0] Then Return SetError(@error + 20, @extended, '') Return SetExtended($aReturn[0], $aReturn[2]) EndFunc ; #FUNCTION# ============================================================================= ; Name...........: SysReadString ; @LarsJ ; ======================================================================================== Func SysReadString( $pBSTR, $iLen = -1 ) If Not $pBSTR Then Return SetError(1, 0, "") If $iLen < 1 Then $iLen = SysStringLen( $pBSTR ) If $iLen < 1 Then Return SetError(2, 0, "") Return DllStructGetData( DllStructCreate( "wchar[" & $iLen & "]", $pBSTR ), 1 ) EndFunc ; #FUNCTION# ============================================================================= ; Name...........: SysStringLen ; @LarsJ ; ======================================================================================== Func SysStringLen( $pBSTR ) If Not $pBSTR Then Return SetError(1, 0, 0) Local $aRet = DllCall( "OleAut32.dll", "uint", "SysStringLen", "ptr", $pBSTR ) If @error Then Return SetError(2, 0, 0) Return $aRet[0] EndFunc