Directly modify a string of a passed parameter in memory

201 views Asked by At

Is it possible to modify the memory value of a function parameter passed by a COM event method? The property value in the COM object needs to be edited.

I'm trying to set a custom user agent for an ActiveX control and re-navigating the loading page with a custom header was not successful if the user selects Refresh or opens a linked page. Also the set header in the Navigate() method does not apply to framed pages.

According to MSDN ( http://msdn.microsoft.com/en-us/library/aa768326%28v=vs.85%29.aspx ), the parameter for the header value is passed as ByRef.

So I tried simply putting a new value to it but it did not work.

So now I'm thinking that it could be achieved if the value stored in the memory is directly changed. So I tried the following but it does not work.

Any idea?

oWB := new WebBrowser("http://sofiablue.net/")

Class WebBrowser
{

    __New(strURL) { 

        static WB
        Gui, New, Resize 
        Gui, Add, ActiveX, vWB w780 h580 , Shell.Explorer  
        Gui, show, w800 h600

        ComObjConnect(WB, this) 

        WB.Navigate(strURL  
            , "_self"
            , null
            , null
            , "User-Agent: tester")
        Loop
           Sleep 10
        Until (WB.readyState=4 && WB.document.readyState="complete" && !WB.busy)    

    }

    BeforeNavigate2(oParams*) {
        ; oParams[6] := "User-Agent: modified" ; this does not work.
        ; StrPut("User-Agent: modified", oParams.GetAddress(6)) ; does not work     
        this.StrPutVar("User-Agent: modified", oParams[6], "utf-16")    ; does not work
    }

    StrPutVar(string, ByRef var, encoding)
    {
        ; Ensure capacity.
        VarSetCapacity( var, StrPut(string, encoding)
            ; StrPut returns char count, but VarSetCapacity needs bytes.
            * ((encoding="utf-16"||encoding="cp1200") ? 2 : 1) )
        ; Copy or convert the string.
        return StrPut(string, &var, encoding)
    }       
}
1

There are 1 answers

0
Lexikos On

AutoHotkey has very limited support for ByRef parameters for COM events.

COM parameters are passed via an array of VARIANTARG structures. The caller supports ByRef by storing the address of their variable in the variant, and setting the type to a bitwise-OR combination of VT_BYREF and the var-type of the parameter, such as VT_VARIANT.

Some languages (such as VBScript) provide a variant of type VT_BYREF|VT_VARIANT (0x400C) by default; perhaps to support ByRef when the type of the parameter isn't known. Because of this, AutoHotkey dereferences such variants automatically. As a result, your BeforeNavigate2 method never receives a reference and cannot output to any of its ByRef Variant parameters.

For any ByRef parameters of a more specific type, such as ByRef Cancel As Boolean, the parameter (in script) should receive an object representing a reference. For example, ComObjType(Cancel) would return VT_BYREF|VT_BOOL (0x400B) and ComObjValue(Cancel) would return the address of a VARIANT_BOOL variable which you can store a boolean value in. The following could be used to store a true value:

if (ComObjType(Cancel) = 0x400B)  ; Safety check
    NumPut(-1, ComObjValue(Cancel), "short")

ByRef in/out parameters of type VT_DISPATCH, VT_UNKNOWN and VT_BSTR have additional requirements. If the previous value is non-NULL, it must be freed first. For VT_BSTR, the new string must be allocated using SysAllocString (which must be called via DllCall).