Jump to content

Recommended Posts

I tried to implement the code in this topic:

Firstly, i have no idea how these lines of code work but meanwhile i noticed that:

; Everytime autoit wants to call a method, get or set a property in a object it needs to go to
; IDispatch::GetIDsFromNames. This is our version of that function, note that by defining this ourselves
; we can fool autoit to believe that the object supports a lot of different properties/methods.
Func __IDispatch_GetIDsFromNames($pSelf, $riid, $rgszNames, $cNames, $lcid, $rgDispId)
...
EndFunc

The problem is i ran into is that some object calls didn't go through IDispatch::GetIDsFromNames.
Here is the code to replicate what i'm mentioning:

Spoiler
;Au3CallByName, Bilgus
Global $Au3_CallByName = 0
Global $hKernel32 = DllOpen("Kernel32.dll")
OnAutoItExitRegister(__CallByNameCleanup)


Func __CallByNameCleanup()
    Au3_CallByName_Init(False) ;Unload
    DllClose($hKernel32)
EndFunc   ;==>__CallByNameCleanup

; Takes a pointer to the v-table in a class and replaces specified member Id in it to a new one.
Func __HookVTableEntry($pVtable, $iVtableOffset, $pHook, ByRef $pOldRet)
    ;;https://www.autoitscript.com/forum/topic/107678-hooking-into-the-idispatch-interface/
    Local Const $PAGE_READWRITE = 0x04
    Local $tpVtable = DllStructCreate("ptr", $pVtable)
    Local $szPtr = DllStructGetSize($tpVtable)
    Local $pFirstEntry, $pEntry, $tEntry, $aCall, $flOldProtect, $bStatus

    ; Dereference the vtable pointer
    $pFirstEntry = DllStructGetData($tpVtable, 1)
    $pEntry = $pFirstEntry + ($iVtableOffset * $szPtr) ;vtable is a big array of pointers 

    ; Make the memory free for all. Yay!
    $aCall = DllCall($hKernel32, "int", "VirtualProtect", "ptr", $pEntry, "long", $szPtr, "dword", $PAGE_READWRITE, "dword*", 0)

    If @error Or Not $aCall[0] Then
        ConsoleWriteError("Error: Failed To hook vTable" & @CRLF)
        Return False
    EndIf
    $flOldProtect = $aCall[4]

    $tEntry = DllStructCreate("ptr", $pEntry)
    $pOldRet = DllStructGetData($tEntry, 1)
    If $pOldRet <> $pHook Then
        DllStructSetData($tEntry, 1, $pHook)
        $bStatus = True
    Else ;Already Hooked
        ConsoleWriteError("Error: vTable is already hooked" & @CRLF)
        $bStatus = False
    EndIf

    ;put the memory protect back how we found it
    DllCall($hKernel32, "int", "VirtualProtect", "ptr", $pEntry, "long", $szPtr, "dword", $flOldProtect, "dword*", 0)
    Return $bStatus
EndFunc   ;==>__HookVTableEntry

; Everytime autoit wants to call a method, get or set a property in a object it needs to go to
; IDispatch::GetIDsFromNames. This is our version of that function, note that by defining this ourselves
; we can fool autoit to believe that the object supports a lot of different properties/methods.
Func __IDispatch_GetIDsFromNames($pSelf, $riid, $rgszNames, $cNames, $lcid, $rgDispId)
    Local Const $DISP_E_UNKNOWNNAME = 0x80020006, $DISPID_UNKNOWN = -1
    Local Static $pGIFN = __Pointer_GetIDsFromNames()
    Local $hRes

    ;Call the original GetIDsFromNames
    $hRes = DllCallAddress("LRESULT", $pGIFN, "ptr", $pSelf, "ptr", $riid, _
            "struct*", $rgszNames, "dword", $cNames, "dword", $lcid, "ptr", $rgDispId)
    If @error Then
        ConsoleWriteError("Error: GetIDsFromNames: " & @error & @CRLF)
        Return $DISP_E_UNKNOWNNAME
    EndIf

    ; Autoit didnt find the name now its our turn
    If $DISPID_UNKNOWN = DllStructGetData(DllStructCreate("long[" & $cNames & "]", $rgDispId), 1, 1) Then
        ;$rgszNames is a pointer to an array[$cNames] of names -- Autoit only asks for one member $cNames = 1
        Local $tName = DllStructCreate("wchar[64]", DllStructGetData(DllStructCreate("ptr[" & $cNames & "]", $rgszNames), 1, 1))
        Local $sName = DllStructGetData($tName, 1)
        ConsoleWrite($sName & @CRLF)

        ;We just prepend CBN_CB_ to the function name and try to call it
        $hRes = Call("CBN_CB_" & $sName, $sName, $pGIFN, $pSelf, $riid, $rgszNames, $cNames, $lcid, $rgDispId)
        If Not @error And $hRes <> Default Then Return $hRes ; User handled the function

        ;Call the original GetIDsFromNames
        $hRes = DllCallAddress("LRESULT", $pGIFN, "ptr", $pSelf, "ptr", $riid, _
                "struct*", $rgszNames, "dword", $cNames, "dword", $lcid, "ptr", $rgDispId)
        If @error Then
            ConsoleWrite("Error: GetIDsFromNames: " & @error & @CRLF)
            Return $DISP_E_UNKNOWNNAME
        EndIf
    EndIf
    Return $hRes[0]
EndFunc   ;==>__IDispatch_GetIDsFromNames

Func __Pointer_GetIDsFromNames($ptr = 0)
    ;Stores pointer to the original 'GetIDsFromNames'
    Local Static $pOldGIFN = $ptr
    If $ptr <> 0 Then $pOldGIFN = $ptr
    Return $pOldGIFN
EndFunc   ;==>__Pointer_GetIDsFromNames

Func Au3_CallByName_Init($bHook = True, $classname = "shell.application")
    Local Const $iOffset_GetIDsFromNames = 5 ;vtable index

    Local Static $IDispatch_GetIDsFromNames_Callback = 0
    Local $oObject, $pObject, $pHook, $pOldGIFN

    If $bHook Then
        If $IDispatch_GetIDsFromNames_Callback = 0 Then
            $IDispatch_GetIDsFromNames_Callback = DllCallbackRegister("__IDispatch_GetIDsFromNames", _
                                                                      "LRESULT", "ptr;ptr;ptr;dword;dword;ptr")
        EndIf
        $pHook = DllCallbackGetPtr($IDispatch_GetIDsFromNames_Callback)
    Else
        $pHook = __Pointer_GetIDsFromNames()
        If $pHook <= 0 Then Return ;Already Unloaded
    EndIf

    $oObject = ObjCreate($classname)
    $pObject = DllStructSetData(DllStructCreate("ptr"), 1, $oObject)

    If __HookVTableEntry($pObject, $iOffset_GetIDsFromNames, $pHook, $pOldGIFN) Then
        __Pointer_GetIDsFromNames($pOldGIFN) ;Save the original pointer to GetIDsFromNames
        If Not $bHook Then
            DllCallbackFree($IDispatch_GetIDsFromNames_Callback)
            $IDispatch_GetIDsFromNames_Callback = 0
        EndIf
    Else
        ;Error
    EndIf

    $oObject = 0
EndFunc   ;==>Au3_CallByName_Init

;|||||||||===========|||||||||
;||||||||| CallBacks |||||||||
Func CBN_CB_Au3_CallByName($sName, $pGIFN, $pSelf, $riid, $rgszNames, $cNames, $lcid, $rgDispId)
    Local Const $DISP_E_UNKNOWNNAME = 0x80020006
    ConsoleWrite(">Call By Name: " & $sName &  " -> " & $Au3_CallByName & @crlf)
    Local Static $tpMember = DllStructCreate("ptr")
    If $Au3_CallByName Then
        Local $hRes, $tMember

        ;ConsoleWrite("CallByName: " & $Au3_CallByName & @CRLF)
        $tMember = DllStructCreate("wchar[" & StringLen($Au3_CallByName) + 1 & "]")
        DllStructSetData($tMember, 1, $Au3_CallByName)
        DllStructSetData($tpMember, 1, DllStructGetPtr($tMember))
        $rgszNames = $tpMember
        $Au3_CallByName = 0

        ;Call the original GetIDsFromNames
        $hRes = DllCallAddress("LRESULT", $pGIFN, "ptr", $pSelf, "ptr", $riid, _
                "struct*", $rgszNames, "dword", $cNames, "dword", $lcid, "ptr", $rgDispId)
        If @error Then
            ConsoleWrite("Error: Call By Name: " & @error & @CRLF)
            Return $DISP_E_UNKNOWNNAME
        EndIf
        Return $hRes[0]
    EndIf
    Return Default ;Default handler
EndFunc

;||||||||| CallBacks |||||||||
;|||||||||===========|||||||||

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;TESTS;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


Au3_CallByName_Init() 

#include <MsgBoxConstants.au3>
#include <Word.au3>

; Create application object
Local $oWord = _Word_Create()
If @error Then Exit MsgBox($MB_SYSTEMMODAL, "Word UDF: _Word_DocTableWrite Example", _
        "Error creating a new Word application object." & @CRLF & "@error = " & @error & ", @extended = " & @extended)
; Open the test document
Local $oDoc = __Word_DocOpen($oWord, @ScriptDir & "\doc.doc", Default, Default, True)
If @error Then Exit MsgBox($MB_SYSTEMMODAL, "Word UDF: _Word_DocTableWrite Example", _
        "Error opening '.\Extras\Test.doc'." & @CRLF & "@error = " & @error & ", @extended = " & @extended)

Func __Word_DocOpen($oAppl, $sFilePath, $bConfirmConversions = Default, $iFormat = Default, $bReadOnly = Default, $bRevert = Default, $bAddToRecentFiles = Default, $sOpenPassword = Default, $sWritePassword = Default)
    If $bConfirmConversions = Default Then $bConfirmConversions = False
    If $iFormat = Default Then $iFormat = $WdOpenFormatAuto
    If $bReadOnly = Default Then $bReadOnly = False
    If $bRevert = Default Then $bRevert = False
    If $bAddToRecentFiles = Default Then $bAddToRecentFiles = False
    If $sOpenPassword = Default Then $sOpenPassword = ""
    If $sWritePassword = Default Then $sWritePassword = ""
    If Not IsObj($oAppl) Then Return SetError(1, 0, 0)
    If StringLeft($sFilePath, "HTTP") = 0 And Not FileExists($sFilePath) Then Return SetError(2, 0, 0)
    If StringInStr($sFilePath, "\") = 0 Then $sFilePath = @ScriptDir & "\" & $sFilePath

    $Au3_CallByName = 'Documents'
    Local $oDoc = $oAppl.Au3_CallByName

    $Au3_CallByName = 'Open'
    ;~ $oDoc = $oDoc.Open($sFilePath, $bConfirmConversions, $bReadOnly, $bAddToRecentFiles, $sOpenPassword, "", $bRevert, $sWritePassword, "", $iFormat) ;this works
    $oDoc = $oDoc.Au3_CallByName($sFilePath, $bConfirmConversions, $bReadOnly, $bAddToRecentFiles, $sOpenPassword, "", $bRevert, $sWritePassword, "", $iFormat)
    If @error Or Not IsObj($oDoc) Then Return SetError(3, @error, 0)
    ; If a read-write document was opened read-only then return an error
    If $bReadOnly = False And $oDoc.Readonly = True Then Return SetError(0, 1, $oDoc)
    Return $oDoc
EndFunc   ;==>_Word_DocOpen

 

I followed the example in the topic and tried to do the same thing with method .Documents (line 193) and .Open (line 194) but didn't get the same result because .Documents was being passed through __IDispatch_GetIDsFromNames while .Open didn't.

$Au3_CallByName = 'Documents'
Local $oDoc = $oAppl.Au3_CallByName
$Au3_CallByName = 'Open'
$oDoc = $oDoc.Au3_CallByName($sFilePath, $bConfirmConversions, $bReadOnly, $bAddToRecentFiles, $sOpenPassword, "", $bRevert, $sWritePassword, "", $iFormat)

Console outputs:

==> The requested action with this object has failed.:
$oDoc = $oDoc.Au3_CallByName($sFilePath, $bConfirmConversions, $bReadOnly, $bAddToRecentFiles, $sOpenPassword, "", $bRevert, $sWritePassword, "", $iFormat)
$oDoc = $oDoc^ ERROR

Is there any workarounds to solve this?

Thank you!

Edited by sylremo
Link to post
Share on other sites

First idont see objcreate

Second you need to check if there is object use:IsObj function

iam ِAutoit programmer.

best thing in life is to use your Brain to

Achieve

everything you want.

Link to post
Share on other sites

Have you tried hooking the word object instead?

Au3_CallByName_Init(True, "Word.Application")

you might need it before or after Word_Create()

 

@ad777 the udf takes care of that

Edited by Bilgus
Link to post
Share on other sites
Posted (edited)

Hi @Bilgus, thank you for your quick response

5 hours ago, Bilgus said:

Have you tried hooking the word object instead?

Yes, i tried but it made no differences.

I came up with another example

Spoiler
#RequireAdmin

Global $Au3_CallByName = 0
Global $hKernel32 = DllOpen("Kernel32.dll")
OnAutoItExitRegister(__CallByNameCleanup)

Global $g___oJSON_Init

Global $sOJsonLibrary = FileRead(@ScriptDir & '\JSON.js')

Global $iError = 0

Au3_CallByName_Init(True, 'HTMLFILE')
$g___oJSON_Obj = ObjCreate("HTMLFILE")

If @error Then
    $iError = 1 
Else
    ;~ ConsoleWrite('IsObj($g___oJSON_Obj.parentwindow) -> ' & IsObj($g___oJSON_Obj.parentwindow) & @CRLF)
    ;~ For $i = 1 To 7
    ;~     ConsoleWrite($i & ' -> ' & ObjName($g___oJSON_Obj, $i) & @CRLF)
    ;~ Next
    $g___oJSON_Obj.parentwindow.execScript($sOJsonLibrary)
    If @error Then
        $iError = 2 
    Else
        $g___oJSON_Init = $g___oJSON_Obj.parentwindow.eval('JSON')
        If @error Then
            $iError = 3
        EndIf
    EndIf
EndIf

$JSON = $g___oJSON_Init.parse('{"title":"text"}')

MsgBox(4096, $iError, $JSON.title)

Func __CallByNameCleanup()
    Au3_CallByName_Init(False)     ;Unload
    DllClose($hKernel32)
EndFunc   ;==>__CallByNameCleanup

Func __HookVTableEntry($pVtable, $iVtableOffset, $pHook, ByRef $pOldRet)
    ;;https://www.autoitscript.com/forum/topic/107678-hooking-into-the-idispatch-interface/
    Local Const $PAGE_READWRITE = 0x04
    Local $tpVtable = DllStructCreate("ptr", $pVtable)
    Local $szPtr = DllStructGetSize($tpVtable)
    Local $pFirstEntry, $pEntry, $tEntry, $aCall, $flOldProtect, $bStatus

    ; Dereference the vtable pointer
    $pFirstEntry = DllStructGetData($tpVtable, 1)
    $pEntry = $pFirstEntry + ($iVtableOffset * $szPtr)     ;vtable is a big array of pointers

    ; Make the memory free for all. Yay!
    $aCall = DllCall($hKernel32, "int", "VirtualProtect", "ptr", $pEntry, "long", $szPtr, "dword", $PAGE_READWRITE, "dword*", 0)

    If @error Or Not $aCall[0] Then
        ConsoleWriteError("Error: Failed To hook vTable" & @CRLF)
        Return False
    EndIf
    $flOldProtect = $aCall[4]

    $tEntry = DllStructCreate("ptr", $pEntry)
    $pOldRet = DllStructGetData($tEntry, 1)
    If $pOldRet <> $pHook Then
        DllStructSetData($tEntry, 1, $pHook)
        $bStatus = True
    Else     ;Already Hooked
        ConsoleWriteError("Error: vTable is already hooked" & @CRLF)
        $bStatus = False
    EndIf

    ;put the memory protect back how we found it
    DllCall($hKernel32, "int", "VirtualProtect", "ptr", $pEntry, "long", $szPtr, "dword", $flOldProtect, "dword*", 0)
    Return $bStatus
EndFunc   ;==>__HookVTableEntry

Func __IDispatch_GetIDsFromNames($pSelf, $riid, $rgszNames, $cNames, $lcid, $rgDispId)
    Local Const $DISP_E_UNKNOWNNAME = 0x80020006, $DISPID_UNKNOWN = -1
    Local Static $pGIFN = __Pointer_GetIDsFromNames()
    Local $hRes

    ;Call the original GetIDsFromNames
    $hRes = DllCallAddress("LRESULT", $pGIFN, "ptr", $pSelf, "ptr", $riid, _
            "struct*", $rgszNames, "dword", $cNames, "dword", $lcid, "ptr", $rgDispId)
    If @error Then
        ConsoleWriteError("Error: GetIDsFromNames: " & @error & @CRLF)
        Return $DISP_E_UNKNOWNNAME
    EndIf

; Autoit didnt find the name now its our turn
;~ If $DISPID_UNKNOWN = DllStructGetData(DllStructCreate("long[" & $cNames & "]", $rgDispId), 1, 1) Then
    ;$rgszNames is a pointer to an array[$cNames] of names -- Autoit only asks for one member $cNames = 1
    Local $tName = DllStructCreate("wchar[64]", DllStructGetData(DllStructCreate("ptr[" & $cNames & "]", $rgszNames), 1, 1))
    Local $sName = DllStructGetData($tName, 1)
    ConsoleWrite('__IDispatch_GetIDsFromNames triggered: ' & $sName & @CRLF)

    ;We just prepend CBN_CB_ to the function name and try to call it
    $hRes = Call("CBN_CB_" & $sName, $sName, $pGIFN, $pSelf, $riid, $rgszNames, $cNames, $lcid, $rgDispId)
    If Not @error And $hRes <> Default Then Return $hRes         ; User handled the function

    ;Call the original GetIDsFromNames
    $hRes = DllCallAddress("LRESULT", $pGIFN, "ptr", $pSelf, "ptr", $riid, _
            "struct*", $rgszNames, "dword", $cNames, "dword", $lcid, "ptr", $rgDispId)
    If @error Then
        ConsoleWrite("Error: GetIDsFromNames: " & @error & @CRLF)
        Return $DISP_E_UNKNOWNNAME
    EndIf
;~ EndIf
    Return $hRes[0]
EndFunc   ;==>__IDispatch_GetIDsFromNames

Func __Pointer_GetIDsFromNames($ptr = 0)
    ;Stores pointer to the original 'GetIDsFromNames'
    Local Static $pOldGIFN = $ptr
    If $ptr <> 0 Then $pOldGIFN = $ptr
    Return $pOldGIFN
EndFunc   ;==>__Pointer_GetIDsFromNames

Func Au3_CallByName_Init($bHook = True, $classname = "shell.application")
    Local Const $iOffset_GetIDsFromNames = 5     ;vtable index

    Local Static $IDispatch_GetIDsFromNames_Callback = 0
    Local $oObject, $pObject, $pHook, $pOldGIFN

    If $bHook Then
        If $IDispatch_GetIDsFromNames_Callback = 0 Then
            $IDispatch_GetIDsFromNames_Callback = DllCallbackRegister("__IDispatch_GetIDsFromNames", _
                    "LRESULT", "ptr;ptr;ptr;dword;dword;ptr")
        EndIf
        $pHook = DllCallbackGetPtr($IDispatch_GetIDsFromNames_Callback)
    Else
        $pHook = __Pointer_GetIDsFromNames()
        If $pHook <= 0 Then Return         ;Already Unloaded
    EndIf

    $oObject = ObjCreate($classname)
    $pObject = DllStructSetData(DllStructCreate("ptr"), 1, $oObject)

    If __HookVTableEntry($pObject, $iOffset_GetIDsFromNames, $pHook, $pOldGIFN) Then
        __Pointer_GetIDsFromNames($pOldGIFN)         ;Save the original pointer to GetIDsFromNames
        If Not $bHook Then
            DllCallbackFree($IDispatch_GetIDsFromNames_Callback)
            $IDispatch_GetIDsFromNames_Callback = 0
        EndIf
    Else
        ;Error
    EndIf

    $oObject = 0
EndFunc   ;==>Au3_CallByName_Init

Func CBN_CB_Au3_CallByName($sName, $pGIFN, $pSelf, $riid, $rgszNames, $cNames, $lcid, $rgDispId)
    Local Const $DISP_E_UNKNOWNNAME = 0x80020006
    ;~ ConsoleWrite(">Call By Name: " & $sName & " -> " & $Au3_CallByName & @CRLF)
    Local Static $tpMember = DllStructCreate("ptr")
    ;~ If $Au3_CallByName Then
        Local $hRes, $tMember

        ;ConsoleWrite("CallByName: " & $Au3_CallByName & @CRLF)
        $tMember = DllStructCreate("wchar[" & StringLen($sName) + 1 & "]")
        DllStructSetData($tMember, 1, $sName)
        DllStructSetData($tpMember, 1, DllStructGetPtr($tMember))
        $rgszNames = $tpMember
        ;~ $Au3_CallByName = 0

        ;Call the original GetIDsFromNames
        $hRes = DllCallAddress("LRESULT", $pGIFN, "ptr", $pSelf, "ptr", $riid, _
                "struct*", $rgszNames, "dword", $cNames, "dword", $lcid, "ptr", $rgDispId)
        If @error Then
            ConsoleWrite("Error: Call By Name: " & @error & @CRLF)
            Return $DISP_E_UNKNOWNNAME
        EndIf
        Return $hRes[0]
    ;~ EndIf
    Return Default     ;Default handler
EndFunc   ;==>CBN_CB_Au3_CallByName

And here is the uglified version of the js file

Spoiler
function xml2json(e){return xml2jsonRecurse(e=cleanXML(e),0)}function xml2jsonRecurse(e){for(var r,n,t,a,s,l={};e.match(/<[^\/][^>]*>/);)r=(s=e.match(/<[^\/][^>]*>/)[0]).substring(1,s.length-1),-1==(n=e.indexOf(s.replace("<","</")))&&(r=s.match(/[^<][\w+$]*/)[0],-1==(n=e.indexOf("</"+r))&&(n=e.indexOf("<\\/"+r))),a=(t=e.substring(s.length,n)).match(/<[^\/][^>]*>/)?xml2json(t):t,void 0===l[r]?l[r]=a:Array.isArray(l[r])?l[r].push(a):l[r]=[l[r],a],e=e.substring(2*s.length+1+t.length);return l}function cleanXML(e){return e=replaceAttributes(e=replaceAloneValues(e=replaceSelfClosingTags(e=(e=(e=(e=(e=e.replace(/<!--[\s\S]*?-->/g,"")).replace(/\n|\t|\r/g,"")).replace(/ {1,}<|\t{1,}</g,"<")).replace(/> {1,}|>\t{1,}/g,">")).replace(/<\?[^>]*\?>/g,""))))}function replaceSelfClosingTags(e){var r=e.match(/<[^/][^>]*\/>/g);if(r)for(var n=0;n<r.length;n++){var t=r[n],a=t.substring(0,t.length-2);a+=">";var s=t.match(/[^<][\w+$]*/)[0],l="</"+s+">",i="<"+s+">",c=a.match(/(\S+)=["']?((?:.(?!["']?\s+(?:\S+)=|[>"']))+.)["']?/g);if(c)for(var g=0;g<c.length;g++){var u=c[g],f=u.substring(0,u.indexOf("="));i+="<"+f+">"+u.substring(u.indexOf('"')+1,u.lastIndexOf('"'))+"</"+f+">"}i+=l,e=e.replace(t,i)}return e}function replaceAloneValues(e){var r=e.match(/<[^\/][^>][^<]+\s+.[^<]+[=][^<]+>{1}([^<]+)/g);if(r)for(var n=0;n<r.length;n++){var t=r[n],a=t.substring(0,t.indexOf(">")+1)+"<_@ttribute>"+t.substring(t.indexOf(">")+1)+"</_@ttribute>";e=e.replace(t,a)}return e}function replaceAttributes(e){var r=e.match(/<[^\/][^>][^<]+\s+.[^<]+[=][^<]+>/g);if(r)for(var n=0;n<r.length;n++){var t=r[n],a="<"+t.match(/[^<][\w+$]*/)[0]+">",s=t.match(/(\S+)=["']?((?:.(?!["']?\s+(?:\S+)=|[>"']))+.)["']?/g);if(s)for(var l=0;l<s.length;l++){var i=s[l],c=i.substring(0,i.indexOf("="));a+="<"+c+">"+i.substring(i.indexOf('"')+1,i.lastIndexOf('"'))+"</"+c+">"}e=e.replace(t,a)}return e};function buildParamlist(t){var e=" p0";t=t||1;for(var r=1;r<t;r++)e=e+" , p"+r;return e}Object.prototype.propAdd=function(prop,val){eval("this."+prop+"="+val)},Object.prototype.methAdd=function(meth,def){eval("this."+meth+"= new "+def)},Object.prototype.jsFunAdd=function(funname,numParams,objectTypeName){var x=buildParamlist(numParams);return objectTypeName=objectTypeName||"Object",eval(objectTypeName+".prototype."+funname+" = function("+x+") { return "+funname+"("+x+"); }")},Object.prototype.protoAdd=function(methName,jsFunction,objectTypeName){objectTypeName=objectTypeName||"Object",eval(objectTypeName+".prototype."+methName+"="+jsFunction)},Object.keys||(Object.keys=function(){"use strict";var o=Object.prototype.hasOwnProperty,a=!{toString:null}.propertyIsEnumerable("toString"),u=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],i=u.length;return function(t){if("object"!=typeof t&&("function"!=typeof t||null===t))throw new TypeError("Object.keys called on non-object");var e,r,n=[];for(e in t)o.call(t,e)&&n.push(e);if(a)for(r=0;r<i;r++)o.call(t,u[r])&&n.push(u[r]);return n}}()),Object.prototype.objGet=function(s){return eval(s)},Array.prototype.index=function(t){return this[t]},Object.prototype.index=function(t){return this[t]},Array.prototype.item=function(t){return this[t]},Object.prototype.item=function(t){return this[t]},Object.prototype.keys=function(){if("object"==typeof this)return Object.keys(this)},Object.prototype.keys=function(t){return (typeof t=="object"?Object.keys(t):Object.keys(this))},Object.prototype.arrayAdd=function(t,e){this[t]=e},Object.prototype.arrayDel=function(t){this.splice(t,1)},Object.prototype.isArray=function(){return this.constructor==Array},Object.prototype.type=function(){return typeof this},Object.prototype.type=function(t){if("undefined"==typeof t){return typeof this}else{return typeof t}};var JSON=new Object;function jsonPath(obj,expr,arg,basename){var P={resultType:arg&&arg.resultType||"VALUE",result:[],normalize:function(t){var r=[];return t.replace(/[\['](\??\(.*?\))[\]']/g,function(t,e){return"[#"+(r.push(e)-1)+"]"}).replace(/'?\.'?|\['?/g,";").replace(/;;;|;;/g,";..;").replace(/;$|'?\]|'$/g,"").replace(/#([0-9]+)/g,function(t,e){return r[e]})},asPath:function(t){for(var e=t.split(";"),r=("undefined"==typeof basename?"$":basename),n=1,o=e.length;n<o;n++)r+=/^[0-9*]+$/.test(e[n])?"["+e[n]+"]":"."+e[n];return r},store:function(t,e){return t&&(P.result[P.result.length]="PATH"==P.resultType?P.asPath(t):e),!!t},trace:function(t,e,r){if(t){var n=t.split(";"),o=n.shift();if(n=n.join(";"),e&&e.hasOwnProperty(o))P.trace(n,e[o],r+";"+o);else if("*"===o)P.walk(o,n,e,r,function(t,e,r,n,o){P.trace(t+";"+r,n,o)});else if(".."===o)P.trace(n,e,r),P.walk(o,n,e,r,function(t,e,r,n,o){"object"==typeof n[t]&&P.trace("..;"+r,n[t],o+";"+t)});else if(/,/.test(o))for(var a=o.split(/'?,'?/),u=0,i=a.length;u<i;u++)P.trace(a[u]+";"+n,e,r);else/^\(.*?\)$/.test(o)?P.trace(P.eval(o,e,r.substr(r.lastIndexOf(";")+1))+";"+n,e,r):/^\?\(.*?\)$/.test(o)?P.walk(o,n,e,r,function(t,e,r,n,o){P.eval(e.replace(/^\?\((.*?)\)$/,"$1"),n[t],t)&&P.trace(t+";"+r,n,o)}):/^(-?[0-9]*):(-?[0-9]*):?([0-9]*)$/.test(o)&&P.slice(o,n,e,r)}else P.store(r,e)},walk:function(t,e,r,n,o){if(r instanceof Array)for(var a=0,u=r.length;a<u;a++)a in r&&o(a,t,e,r,n);else if("object"==typeof r)for(var i in r)r.hasOwnProperty(i)&&o(i,t,e,r,n)},slice:function(t,e,r,n){if(r instanceof Array){var o=r.length,a=0,u=o,i=1;t.replace(/^(-?[0-9]*):(-?[0-9]*):?(-?[0-9]*)$/g,function(t,e,r,n){a=parseInt(e||a),u=parseInt(r||u),i=parseInt(n||i)}),a=a<0?Math.max(0,a+o):Math.min(o,a),u=u<0?Math.max(0,u+o):Math.min(o,u);for(var p=a;p<u;p+=i)P.trace(p+";"+e,r,n)}},eval:function(x,_v,_vname){try{return $&&_v&&eval(x.replace(/@/g,"_v"))}catch(t){throw new SyntaxError("jsonPath: "+t.message+": "+x.replace(/@/g,"_v").replace(/\^/g,"_a"))}}},$=obj;if(expr&&obj&&("VALUE"==P.resultType||"PATH"==P.resultType))return P.trace(P.normalize(expr).replace(/^\$;/,""),obj,"$"),!!P.result.length&&P.result}function oLiteral(t){this.literal=t}function protectDoubleQuotes(t){return t.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}JSON.jsonPath=function(t,e,r,basename){return jsonPath(t,e,r,basename)},"object"!=typeof JSON&&(JSON={}),function(){"use strict";function f(t){return t<10?"0"+t:t}var cx,escapable,gap,indent,meta,rep;function quote(t){return escapable.lastIndex=0,escapable.test(t)?'"'+t.replace(escapable,function(t){var e=meta[t];return"string"==typeof e?e:"\\u"+("0000"+t.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+t+'"'}function str(t,e){var r,n,o,a,u,i=gap,p=e[t];switch(p&&"object"==typeof p&&"function"==typeof p.toJSON&&(p=p.toJSON(t)),"function"==typeof rep&&(p=rep.call(e,t,p)),typeof p){case"string":return quote(p);case"number":return isFinite(p)?String(p):"null";case"boolean":case"null":return String(p);case"object":if(!p)return"null";if(gap+=indent,u=[],"[object Array]"===Object.prototype.toString.apply(p)){for(a=p.length,r=0;r<a;r+=1)u[r]=str(r,p)||"null";return o=0===u.length?"[]":gap?"[\n"+gap+u.join(",\n"+gap)+"\n"+i+"]":"["+u.join(",")+"]",gap=i,o}if(rep&&"object"==typeof rep)for(a=rep.length,r=0;r<a;r+=1)"string"==typeof rep[r]&&(o=str(n=rep[r],p))&&u.push(quote(n)+(gap?": ":":")+o);else for(n in p)Object.prototype.hasOwnProperty.call(p,n)&&(o=str(n,p))&&u.push(quote(n)+(gap?": ":":")+o);return o=0===u.length?"{}":gap?"{\n"+gap+u.join(",\n"+gap)+"\n"+i+"}":"{"+u.join(",")+"}",gap=i,o}}"function"!=typeof Date.prototype.toJSON&&(Date.prototype.toJSON=function(){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null},String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(){return this.valueOf()}),"function"!=typeof JSON.stringify&&(escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,meta={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},JSON.stringify=function(t,e,r){var n;if(indent=gap="","number"==typeof r)for(n=0;n<r;n+=1)indent+=" ";else"string"==typeof r&&(indent=r);if((rep=e)&&"function"!=typeof e&&("object"!=typeof e||"number"!=typeof e.length))throw new Error("JSON.stringify");return str("",{"":t})}),"function"!=typeof JSON.parse&&(cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,JSON.parse=function(text,reviver){var j;function walk(t,e){var r,n,o=t[e];if(o&&"object"==typeof o)for(r in o)Object.prototype.hasOwnProperty.call(o,r)&&(void 0!==(n=walk(o,r))?o[r]=n:delete o[r]);return reviver.call(t,e,o)}if(text=String(text),cx.lastIndex=0,cx.test(text)&&(text=text.replace(cx,function(t){return"\\u"+("0000"+t.charCodeAt(0).toString(16)).slice(-4)})),/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return j=eval("("+text+")"),"function"==typeof reviver?walk({"":j},""):j;throw new SyntaxError("JSON.parse")})}(),Object.prototype.stringify=function(){return JSON.stringify(this)},Object.prototype.parse=function(t){return JSON.parse(t)},Object.prototype.jsonPath=function(t,e,basename){return JSON.jsonPath(this,t,(e==true?{resultType:"PATH"}:e),basename)},Object.prototype.objToString=function(){return JSON.stringify(this)},Object.prototype.strToObject=function(t){return JSON.parse(t)},Object.prototype.dot=function(str,jsStrFun){return"string"==typeof str?eval('"'+protectDoubleQuotes(str)+'".'+jsStrFun):eval(str+"."+jsStrFun)},Object.prototype.toObj=function(literal){return"string"==typeof literal?eval('new oLiteral("'+protectDoubleQuotes(literal)+'")'):eval("new oLiteral("+literal+")")},Object.prototype.jsMethAdd=function(funname,numParams){var x=buildParamlist(numParams);return eval("oLiteral.prototype."+funname+" = function("+x+"){return this.literal."+funname+"("+x+"); }")};Object.prototype.beautify=function(r){return JSON.stringify(this,null,typeof r=='undefined'?4:r)},Object.prototype.prettify=Object.prototype.beautify,Object.prototype.toStr=function(r){if(r<0){return JSON.stringify(this.stringify())}else{return JSON.stringify(this,null,typeof r=='undefined'?null:r)}},Object.prototype.sort=function(){},Object.prototype.reverse=function(){},Object.prototype.min=function(){return Math.min.apply(null,this)},Object.prototype.max=function(){return Math.max.apply(null,this)},JSON.filter=JSON.jsonPath,Object.prototype.filter=Object.prototype.jsonPath,Object.prototype.parseXML=function(t){return JSON.parse(xml2json(t).toStr())},Object.prototype.get=function(jsonPath,obj2str){var val=eval("this"+checkkey(jsonPath).replace(/\.(\d+)\b/g,"[$1]"));if(typeof val=="object"&&"undefined"!=typeof obj2str){val=val.toStr(obj2str)};return val},Object.prototype.set=function(key_name,val){eval("this"+checkkey(key_name).replace(/\.(?:item|index)\((\d+)\)/g,"[$1]").replace(/\.(\d+)\b/g,"[$1]")+"="+val)},Object.prototype.remove=function(key_name){eval("delete this."+key_name)},Object.prototype.values=function(){var oValues=[];for(var key in this){if(this.hasOwnProperty(key)){oValues.push(eval("this."+key))}};return oValues};function search(path,obj,target,regexMode){var aPath=[];var val;function json_search(path,obj,target,regexMode){for(var keyname in obj){if(obj.hasOwnProperty(keyname)){val=obj[keyname];if(regexMode==true&&"string"==typeof val&&val.match(target)){aPath.push(path+(isNaN(keyname)?"."+keyname:'['+keyname+']'))}else if(val===target){aPath.push(path+(isNaN(keyname)?"."+keyname:'['+keyname+']'))}else if(typeof val==="object"){json_search(path+(isNaN(keyname)?"."+keyname:'['+keyname+']'),val,target,regexMode)}}}};json_search(path,obj,target,regexMode);return aPath};Object.prototype.findPath=function(node,regexMode){return search("this",this,node,regexMode)};function checkkey(keyname){if(!isNaN(keyname)){keyname="['"+keyname+"']"}if(keyname.substr(0,1)!=="["){keyname="."+keyname}return keyname}

 

 


This JSON object after calling parse method will accept every method and property names, so obviously it can not be passed through __IDispatch_GetIDsFromNames, so i think maybe i will try to intercept every dot statement, and this is the question i have for this post.

I tried to hook the HTMLFILE object, place it both before and after the ObjCreate statement.

Au3_CallByName_Init(True, 'HTMLFILE')

This time i commented out the "If" statement that indicate that AutoIt didn't find the method name (now __IDispatch_GetIDsFromNames should be triggered on every dot statement), slightly modified CBN_CB_Au3_CallByName to use its own param $sName as method name instead of $Au3_CallByName, and added a trace line in order to track those names.

Func __IDispatch_GetIDsFromNames($pSelf, $riid, $rgszNames, $cNames, $lcid, $rgDispId)
    Local Const $DISP_E_UNKNOWNNAME = 0x80020006, $DISPID_UNKNOWN = -1
    Local Static $pGIFN = __Pointer_GetIDsFromNames()
    Local $hRes

    ;Call the original GetIDsFromNames
    $hRes = DllCallAddress("LRESULT", $pGIFN, "ptr", $pSelf, "ptr", $riid, _
            "struct*", $rgszNames, "dword", $cNames, "dword", $lcid, "ptr", $rgDispId)
    If @error Then
        ConsoleWriteError("Error: GetIDsFromNames: " & @error & @CRLF)
        Return $DISP_E_UNKNOWNNAME
    EndIf

    ; Autoit didnt find the name now its our turn
    ;~ If $DISPID_UNKNOWN = DllStructGetData(DllStructCreate("long[" & $cNames & "]", $rgDispId), 1, 1) Then
        ;$rgszNames is a pointer to an array[$cNames] of names -- Autoit only asks for one member $cNames = 1
        Local $tName = DllStructCreate("wchar[64]", DllStructGetData(DllStructCreate("ptr[" & $cNames & "]", $rgszNames), 1, 1))
        Local $sName = DllStructGetData($tName, 1)
        ConsoleWrite('__IDispatch_GetIDsFromNames triggered: ' & $sName & @CRLF)

        ;We just prepend CBN_CB_ to the function name and try to call it
        $hRes = Call("CBN_CB_" & $sName, $sName, $pGIFN, $pSelf, $riid, $rgszNames, $cNames, $lcid, $rgDispId)
        If Not @error And $hRes <> Default Then Return $hRes         ; User handled the function

        ;Call the original GetIDsFromNames
        $hRes = DllCallAddress("LRESULT", $pGIFN, "ptr", $pSelf, "ptr", $riid, _
                "struct*", $rgszNames, "dword", $cNames, "dword", $lcid, "ptr", $rgDispId)
        If @error Then
            ConsoleWrite("Error: GetIDsFromNames: " & @error & @CRLF)
            Return $DISP_E_UNKNOWNNAME
        EndIf
    ;~ EndIf
    Return $hRes[0]
EndFunc   ;==>__IDispatch_GetIDsFromNames
Func CBN_CB_Au3_CallByName($sName, $pGIFN, $pSelf, $riid, $rgszNames, $cNames, $lcid, $rgDispId)
    Local Const $DISP_E_UNKNOWNNAME = 0x80020006
    ;~ ConsoleWrite(">Call By Name: " & $sName & " -> " & $Au3_CallByName & @CRLF)
    Local Static $tpMember = DllStructCreate("ptr")
    ;~ If $Au3_CallByName Then
        Local $hRes, $tMember

        ;ConsoleWrite("CallByName: " & $Au3_CallByName & @CRLF)
        $tMember = DllStructCreate("wchar[" & StringLen($sName) + 1 & "]")
        DllStructSetData($tMember, 1, $sName)
        DllStructSetData($tpMember, 1, DllStructGetPtr($tMember))
        $rgszNames = $tpMember
        ;~ $Au3_CallByName = 0

        ;Call the original GetIDsFromNames
        $hRes = DllCallAddress("LRESULT", $pGIFN, "ptr", $pSelf, "ptr", $riid, _
                "struct*", $rgszNames, "dword", $cNames, "dword", $lcid, "ptr", $rgDispId)
        If @error Then
            ConsoleWrite("Error: Call By Name: " & @error & @CRLF)
            Return $DISP_E_UNKNOWNNAME
        EndIf
        Return $hRes[0]
    ;~ EndIf
    Return Default     ;Default handler
EndFunc   ;==>CBN_CB_Au3_CallByName


Here are the console outputs:

__IDispatch_GetIDsFromNames triggered: parentwindow
__IDispatch_GetIDsFromNames triggered: parentwindow

Of course i did manually check with IsObj to make sure that every dot statement is being used on a valid object. And according to console, only parentwindow was caught, while execScript, eval, parse, title didn't.

Edited by sylremo
provide more infos, correct grammars
Link to post
Share on other sites

Sorry you haven't gotten any satisfactory answers so far, I don't have a windows machine to test on ATM so I'm not of much help

Likely whats going on is the object is in a different process 'multithreaded apartment' you could look at the

TLB in a decent object browser Com View https://www.softpedia.com/get/System/System-Info/COMView.shtml

 

 

 

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By SEuBo
      Hi there,
      while I created an example script to generate and execute a function during runtime, I stumbled across a neat way to share data between running autoit scripts.
      This is done using the amazing magic of  AutoItObject_Internal . (You'll need at least Version 3.0.0 of AutoItObject_Internal)
      Using this UDF, you can create a shared data storage, basically an empty "AutoitObject_Internal-"Object which you can then use to write / read data Inline. no set/get methods, just
      #include "AutoItSharedData.au3" $oShare = _AutoIt_SharedData_CreateOrAttach("MyCustomID") $oShare.some_data = 'foo' and you're done. any other script accessing this data will have to do:
      #include "AutoItSharedData.au3" $oShare = _AutoIt_SharedData_CreateOrAttach("MyCustomID") ConsoleWrite($oShare.some_data & @LF)  
      Basically it's Larsj's Implementing IRunningObjectTable Interface, but you dont have a Dictionary, but an IDIspatch Object instead.
      There are already a bunch of IPC options available - and this is another one.
      AutoItSharedData.au3
       
      Example Script 1
       
      Example Script 2
      Output: 
      To test: run Example Script 1, Then run example Script 2.. or the other way around.
      Example Script 3
      Example_sharedata3.au3
      Example_sharedata3_Controlsend.au3
      Example_sharedata3_Tooltip.au3
      To test: run Example_sharedata3.au3.
      Output: 
       
       Example SharedData4:
      Output: 
      /Edit: Please note that there's a limitation with the Running object table :
      The Script accessing a variable first, will be the "server" for this variable. This means, access to that variable from other scripts should only be possible, as long the "server" script is running! Use appropriate Object Error handlers in case you don't want the surviving "clients" to crash.
      Feedback and/or improvements appreciated
       
      changelog
      version 2.0
      Removed need for AutoItObject, as AutoItObject_Internal now comes with ROT support Added UDF Header Fixed typo on "#include AutoItObjectInternal.au3" -> "#include AutoItObject_Internal.au3" Added ObjGet() after registering the object fails (in case 2 programs tried to register the same ID simultaneously) Updated Examples & zip archive. Cheers,
       
      AutoItSharedData.zip
    • By genius257
      I've made a library, based on AutoItObject UDF with the goal of implementing getter and setter functionality and make it possible to define new object properties in as few steps as possible.
      Thank you to @trancexx for getting me on the right track, and all users in Hooking into the IDispatch interface for the code to get me going.
      If I've forgotten to add credit, please let me know
      Example:
      #include "AutoItObject_Internal.au3" $myCar = IDispatch() $myCar.make = 'Ford' $myCar.model = 'Mustang' $myCar.year = 1969 $myCar.__defineGetter('DisplayCar', DisplayCar) Func DisplayCar($oThis) Return 'A Beautiful ' & $oThis.parent.year & ' ' & $oThis.parent.make & ' ' & $oThis.parent.model EndFunc MsgBox(0, "", $myCar.DisplayCar) More examples: https://github.com/genius257/AutoItObject-Internal/tree/master/Examples
      Version: 3.0.0
      AutoItObject_Internal.au3
      Documentation
      Edit2 (19th March 2017):
      First of all, sorry about the lack of updates on this project. I always start too many projects and end up ignoring old projects, if I run into problems ^^'.
      So I've started moving my AutoIt scripts to GitHub. I will still post the most recent script version here.
    • By nacerbaaziz
      hello autoit team
      please
      i tried to create a SPVoice object 
      when i create the object and tried to use this function SetAlertBoundary
      it gave me an error
      please where is the problem?
      here is the code
      local $o_Sapi_OBJ = ObjCreate("SAPI.SpVoice") if IsObj($o_Sapi_OBJ) then $o_Sapi_OBJ.SetAlertBoundary("SPEI_PHONEME") endIf note i got the function name from microsoft web site
       
      https://docs.microsoft.com/en-us/previous-versions/windows/desktop/ms719784(v=vs.85)
      i have windows10
    • By Colduction
      Hi AutoIt Programmers!

      I've seen a code that gives Name of Group by writing it's group's SID, but this one response very slower than Windows Command-Line WMIC
       
      Func _GetLocalGroupName($sSID = 'S-1-5-18') $objWMIService = ObjGet ("winmgmts:\\" & @ComputerName & "\root\cimv2") $colItems = $objWMIService.ExecQuery('SELECT Name FROM Win32_Group where SID="' & $sSID & '"') For $GroupNames in $colItems MsgBox (0,"",$GroupNames.Name) ExitLoop Next EndFunc I don't want call and use any third-party programs even CMD, i just want use from Windows API, netapi32.dll or AutoIt Functions (Standalone).
      Do you have any idea to improve speed/performance of this code? I'll happy of your comments
       
       
       
      ====================== SOLOUTION by @Subz ======================
       
    • By Colduction
      Hello again, i have a code that changes username to favorite, my problem is how to use ObjEvent() function to catch errors, i've red Help File and Forum's Topics but i can't understand too much😐

      Here is a code (I've copied this codes from a user of AutoIt Forum):
       
      $sOldUser = "Administrator" $sNewUser = "Admin" $oUser = ObjGet("WinNT://" & @ComputerName & "/" & $sOldUser & ",user") $oComputer = ObjGet("WinNT://" & @ComputerName) $oNewUser = $oComputer.MoveHere($oUser.ADsPath, $sNewUser) Thanks for your care, I'm new to AutoIt and days should be passed with my coding and practicing to don't bother you :)❤
×
×
  • Create New...