Shoutbox

Active Accessibility Objects and ReadInterfacePtr - Printable Version

-Shoutbox (https://shoutbox.menthix.net)
+-- Forum: MsgHelp Archive (/forumdisplay.php?fid=58)
+--- Forum: Messenger Plus! for Live Messenger (/forumdisplay.php?fid=4)
+---- Forum: Scripting (/forumdisplay.php?fid=39)
+----- Thread: Active Accessibility Objects and ReadInterfacePtr (/showthread.php?tid=93745)

Active Accessibility Objects and ReadInterfacePtr by matty on 02-03-2010 at 01:26 AM

Ok so for those who do not understand the code please at the moment don't ask about it. I am stumped on the following:

Javascript code:
if (Messenger.MyStatus === STATUS_UNKNOWN) {
   
    Debug.DebuggingWindowVisible = true;
   
    var hWnd = Interop.Call('user32', 'FindWindowExW', Messenger.ContactListWndHandle, 0, 'Main Window Class', '');
    hWnd = Interop.Call('user32', 'FindWindowExW', hWnd, 0, 'DirectUIHWND', '');
     
    var IID_IAccessible = Interop.Allocate(16);
    with (IID_IAccessible) {
        WriteDWORD(0, 0x618736E0);
        WriteWORD(4, 0x3C3D);
        WriteWORD(6, 0x11CF);
        SetAt(8, 0x81);
        SetAt(9, 0xc);
        SetAt(10, 0x0);
        SetAt(11, 0xaa);
        SetAt(12, 0x0);
        SetAt(13, 0x38);
        SetAt(14, 0x9b);
        SetAt(15, 0x71);
    }
     
    var pAccessibleData = Interop.Allocate(4);
    if(Interop.Call('oleacc', 'AccessibleObjectFromWindow', hWnd, 0xFFFFFFFC /* OBJID_CLIENT */, IID_IAccessible, pAccessibleData) === 0) {
        var iAccessible = pAccessibleData.ReadInterfacePtr(0);
        if(iAccessible) {
            var iAccessibleChildren = Interop.Allocate(16*iAccessible.accChildCount);
            var iAccessibleChildrenFound = Interop.Allocate(4);
            if (Interop.Call('oleacc', 'AccessibleChildren', iAccessible, 0, iAccessible.accChildCount, iAccessibleChildren, iAccessibleChildrenFound) === 0){
                for (var i=0; i<iAccessibleChildrenFound.ReadDWORD(0); ++i) {
                    if (iAccessibleChildren.ReadDWORD(i*16) === 0x9 /* VT_DISPATCH */) {
                        var iAccessibleChild = iAccessibleChildren.ReadInterfacePtr(i*16+8);
                        if (iAccessibleChild) {
                            try{
                                Debug.Trace(iAccessible.accName(iAccessibleChild));                            }catch(e){
                                Debug.Trace('epic fail #5');
                            }
                        } else {
                            Debug.Trace('epic fail #4');
                        }
                    }                  
                    else {
                        Debug.Trace('epic ail #3');
                    }
                }
            }
            else {
                Debug.Trace('epic ail #2');
            }
        }
        else {
            Debug.Trace('epic ail #1');
        }
    }
}


Currently I have no problem getting the initial iAccessible interface. The problem lies with being able to get even the Names of the child objects.

I have tried many different variations for the highlighted code but to no avail. Note the code only works on the contact list window that is not signed in yet.

I have tried
  • iAccessibleChild.accName()
  • Copying the pointer to a new databloc and using ReadInterfacePtr
  • the list goes on; but I forget all that I have tried.


RE: Active Accessibility Objects and ReadInterfacePtr by Choli on 02-05-2010 at 05:44 PM

quote:
Originally posted by matty
iAccessibleChild.accName()
I'm not a expert in idispatch interfaces and these things but acording to IAccessible Interface it is either ".accName" (without parenthesis) or ".get_accName()". What I don't understand or know is if you have to use iAccessible.get_accName() or iAccessibleChild.get_accName()

quote:
Originally posted by matty
Copying the pointer to a new databloc and using ReadInterfacePtr
with this you mean something like this?
Javascript code:
var temp = Interop.Allocate(4);
CopyMemory(temp, iAccessibleChildren.ReadDWORD(i*16+8), 4); // this copyMemory is this: http://msdn.microsoft.com/en-us/library/aa366535%28VS.85%29.aspx
var iAccessibleChild = temp.ReadInterfacePtr(0);

I don't know if this will work (because i don't understand if IDispatch is a pointer by itself or not (i'm a bit confused about what's being explained in VARIANT and VARIANTARG)

quote:
Originally posted by matty
Javascript code:
if (iAccessibleChildren.ReadDWORD(i*16) === 0x9 /* VT_DISPATCH */) {


This is not the problem you're having, but don't you think that line should use ReadWORD instead of ReadDWORD?
RE: Active Accessibility Objects and ReadInterfacePtr by matty on 02-05-2010 at 06:37 PM

quote:
Originally posted by Choli
This is not the problem you're having, but don't you think that line should use ReadWORD instead of ReadDWORD?
Not by the looks of the VARIANT structure iAccessible uses:
http://msdn.microsoft.com/en-us/library/dd373687%28VS.85%29.aspx
RE: Active Accessibility Objects and ReadInterfacePtr by Mnjul on 02-05-2010 at 06:45 PM

I think it's WORD, as VARTYPE is type-defined unsigned short.
http://msdn.microsoft.com/en-us/library/aa910805.aspx


RE: Active Accessibility Objects and ReadInterfacePtr by matty on 02-05-2010 at 07:01 PM

Interesting... I will give it a shot when I get home...


RE: Active Accessibility Objects and ReadInterfacePtr by Eljay on 02-08-2010 at 10:36 PM

Just using .accName gets the property fine, the reason the exception is being thrown is that it is of type "unknown".
After many varied attempts at making it work, I have come to the conclusion JScript sucks at this stuff :P

Strangely enough, if you run it when signed in, all the children have accName type as unknown except for the advertisement area which actually returns a string containing the url of the advertisement. Even though the proper accName of that child should just be "Advertisement", with the url actually being the accName of another child of the Advertisement child, which I don't understand at all.

The only property that seems accessible is accChildCount, all others return type "unknown". Pity because this seems quite fun to play around with if it worked :P


RE: Active Accessibility Objects and ReadInterfacePtr by matty on 02-09-2010 at 03:51 AM

This works thanks to Patchy!

Javascript code:
if (Messenger.MyStatus === STATUS_UNKNOWN) {
   
    Debug.DebuggingWindowVisible = true;
    Debug.ClearDebuggingWindow();
   
    var hWnd = Interop.Call('user32', 'FindWindowExW', Messenger.ContactListWndHandle, 0, 'Main Window Class', '');
    hWnd = Interop.Call('user32', 'FindWindowExW', hWnd, 0, 'DirectUIHWND', '');
     
    var IID_IAccessible = Interop.Allocate(16);
    Interop.Call('ole32', 'IIDFromString', '{618736E0-3C3D-11CF-810C-00AA00389B71}', IID_IAccessible);
     
    var pAccessibleData = Interop.Allocate(4);
    if(Interop.Call('oleacc', 'AccessibleObjectFromWindow', hWnd, 0xFFFFFFFC, IID_IAccessible, pAccessibleData) === 0) {
        var iAccessible = pAccessibleData.ReadInterfacePtr(0);
        if(iAccessible) {
            var iAccessibleChildren = Interop.Allocate(16*iAccessible.accChildCount);
            var iAccessibleChildrenFound = Interop.Allocate(4);
            if (Interop.Call('oleacc', 'AccessibleChildren', iAccessible, 0, iAccessible.accChildCount, iAccessibleChildren, iAccessibleChildrenFound) === 0){
            Debug.Trace('Child Count: '+iAccessibleChildrenFound.ReadDWORD(0));
                for (var i=0; i<iAccessibleChildrenFound.ReadDWORD(0); ++i) {
                    if (iAccessibleChildren.ReadDWORD(i*16) === 0x9) {
                        var iAccessibleChild = iAccessibleChildren.ReadInterfacePtr(i*16+8);
                        if (iAccessibleChild) {
                            try{
                                if (iAccessibleChild.accName(0).match ( /E-mail+/)) {
                                    iAccessibleChild.accValue(0) = 'test@test.com';
                                }
                                if (iAccessibleChild.accName(0).match ( /Status+/)) {
                                    //Doesn't work not sure why...
                                    //iAccessibleChild.accValue(0) = 'Busy';
                                }
                               
                                Debug.Trace(iAccessibleChild.accName(0)+': '+iAccessibleChild.accValue(0));
                            }catch(e){
                                //Most likely the password edit box as you cannot access it...
                                Debug.Trace(e.number + ' /\\ ' + e.description);
                            }
                        }
                    }
                }
            }
        }
    }
}


RE: Active Accessibility Objects and ReadInterfacePtr by Eljay on 02-09-2010 at 06:43 PM

Well that's an annoying simple way of doing it after all the crap I tried :P Now to clean up this mess you have created so it is actually useful!

Starting with the IID stuff which can just be done much simpler like so:

JScript code:
Interop.Call('ole32', 'IIDFromString', '{618736E0-3C3D-11CF-810C-00AA00389B71}', IID_IAccessible);


It seems like a nice thing to make proper wrapper classes for, if only I could think of a good use for it... *-)