• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1331
  • Last Modified:

PInvoke Help Needed

I'm trying to utilize the AccessibleObjectFromWindow method of the Active Accessiblity SDK.   It is defined as follows (from the sdk documentation):

STDAPI AccessibleObjectFromWindow(
  HWND hwnd,
  DWORD dwObjectID,
  REFIID riid,
  void** ppvObject

I have defined it in my C# code as:

[DllImport("Oleacc.dll", EntryPoint="AccessibleObjectFromWindow")]
    private static extern int _AccessibleObjectFromWindow(int hwnd,
        int dwObjectID,
        System.Guid riid,
        out System.IntPtr ppvObject);

I also have the following defined to pass parameters for dwObjectID and riid:

public static Guid IDD_IACCESSIBLE = new Guid(0x618736e0, 0x3c3d, 0x11cf, 0x81, 0x0c, 0x00,0xaa, 0x00, 0x38, 0x9b,0x71);
            public static int OBJID_WINDOW = 0x00000000;

Now I've written a function to wrap that as follows:

public static int AccessibleObjectFromWindow(int hwnd, int dwObjectID, System.Guid riid, IAccessible ppvObject)
                  //IntPtr ptr = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(IntPtr)));
                  IntPtr ptr = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(IntPtr)));
                  Marshal.WriteIntPtr(ptr, IntPtr.Zero);

                  int result = _AccessibleObjectFromWindow(hwnd, dwObjectID, riid, out ptr);
                  if (result == 0)
                        ppvObject = (IAccessible)Marshal.GetObjectForIUnknown(Marshal.ReadIntPtr(ptr));
                  return result;

And call it with:

int hr = WAccessible.AccessibleObjectFromWindow(hwnd, WAccessible.OBJID_WINDOW, WAccessible.IDD_IACCESSIBLE ,acc);

In this call, the hwnd is set from a call to FindWindow from User32.dll, acc is defined as IAccessible and is null.

The result of the _AccessibleObjectFromWindow(hwnd, dwObjectID, riid, out ptr); call turns out to be an Invalid Argument Exception and I can't figure out why.  The only possiblity I can think of is that possibly doing something wrong with the pointers.  

Please help!


I just want to add that the SDK documentation on AccessibleObjectFromWindow is available Here:  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msaa/msaaccrf_2r7b.asp

  • 3
1 Solution
Try this declaration....

 [DllImport("oleacc.dll", ExactSpelling=true, PreserveSig=false)]
 [return: MarshalAs(UnmanagedType.Interface)]
 public static extern object AccessibleObjectFromWindow(
    IntPtr hwnd,
    uint dwObjectID,
    [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid);
Then you can try to cast the returned object as IAccessible
andyalmqAuthor Commented:
That appears to have worked correctly, but could you please try to explain what I was doing wrong?  I understand what ExactSpelling and PreserveSig did.  

Was there a specific reason for returning the out parameter as the return value? (other than as the framework documentation says of not needing it)

Why return the object as an interface rather than a pointer to it?  is this due to the fact that that it was originally defined as void**?

I'd really appreciate these answers.

It's more difficult that way. Basically, ppvObject is IUnknown object and needed to be marshalled to IAccessible which makes it more difficult.

To implement like the one i proposed make it easier since we can specify the return argument and choose to ignore HRESULT from the api. When PreservSig is set to false, a call that returns an HRESULT of S_OK is transformed such that the [out, retval] parameter is used as the function return value.

Featured Post

[Webinar On Demand] Database Backup and Recovery

Does your company store data on premises, off site, in the cloud, or a combination of these? If you answered “yes”, you need a data backup recovery plan that fits each and every platform. Watch now as as Percona teaches us how to build agile data backup recovery plan.

  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now