[Accessibility-ia2] registering a proxy dll

Michael Curran mick at kulgan.net
Wed Mar 19 06:58:09 PDT 2008

Hi all,

For a long while now, I have been aware of a limitation of IAccessible2, 
when used in a portable situation with an out-of-process AT. For 
example: where either the AT is on a usb key, or both the AT and the 
application are on a USB key. In this example USB key is really talking 
about the fact that the product is not installed on the system, it could 
be on a read-only drive, and it may have very limited user privilages.

both NVDA and Accessibility Probe are examples of out-of-process ATs.

When asking for an IAccessible2 object from an application over a 
process boundary, a IA2 proxy dll must be registered in order for the OS 
to understand how to martial the information. Up until now both NVDA 
developers and Accessibility Probe developers were under the impression 
that you have to register the IAccessible2 dll in the registry using 
regsvr32. And of course to do this, you probably need elevated user 
privilages which usually means doing this at install time.

However, thanks to a particular person on the IA2 panel at CSUN, I now 
have a much clearer idea on how to solve this issue.

The steps to make an interface usable with out registering the dll are 
as follows:

*Load the DLL library in to the process with something like LoadLibrary 
or CoLoadLibrary.
*Look up the DllGetClassObject function in this dll with GetProcAddress.
*Call the DllGetClassObject function giving it IID_IAccessible2, 
IID_IUnknown, and a pointer to an IUnknown (which will receive the newly 
instanciated class object).
This class object is a class factory which can create all the 
IAccessible2 interfaces.
*Call CoRegisterClassObject, giving it IID_IAccessible2, the IUnknown 
and a pointer to a long (where a special registration cooky can be 
stored for later use). This step lets your process know about this class 
object. All requests to create IAccessible2 interfaces will go to this 
class object.
*Finally call CoRegisterPSClsid for each of the IAccessible2 interface 
IIDs, and IID_IAccessible2. This step tells your process that for any of 
these IIDs, use the class object that was registered under the IID of 

There is another step, that you need to perform once you are finnished 
with IAccessible2 (probably when your process is about to terminate) and 
that is:
*Call CoRevokeClassObject, giving it that registration cooky you got 
from CoRegisterClassObject. This unregisters the class object from your 
process, and also makes sure it gets cleaned up etc.

However, all these steps must be executed in each apartment that needs 
to access or create IAccessible2 objects. So this means that the steps 
need to be performed both in the AT and in the application.

This also indirectly means that the IA2 proxy dll must not only be 
included with the AT, but also included with the application as well.

I have been trying to work out a way so that the application does not 
need to perform these steps, but I don't think it is possible. It seems 
both the AT and the application must understand the martialling 
techniques for all the interfaces.

Here is a bit of c++ code which clearly shows how to make IA2 work in a 

I do strongly believe it is important for ATs such as NVDA to be able to 
access IAccessible2 applications (such as Firefox3) even if  NVDA is run 
off a USB key. Blind and vision impaired people are wanting a truely 
portable screen reader more and more, so they can simply go up to any 
computer (whether it be at a university or a friend's house or perhaps a 
net cafe, and wack in their USB key and be able to use the system). NVDA 
is fully portable except for IAcessible2 support.

As I have also noted, this does also effect Accessibility probe, which 
currently needs you to manually register actf-ia2.dll before you can 
view IAccessible2 objects.

We have two options about how to move forward in making sure that 
out-of-process ATs can use IAccessible2 portably:
1. The AT sets up IA2 support in its own process, and the application 
also sets up IA2 support in its own process (example: NVDA, and 
Firefox3). This means two copies of the dll, and a change of code to 
both NVDA and Firefox3.
2. The AT sets up IA2 support in its own process, but then injects a 
small bit of code in to the application, which sets up IA2 support in 
the application, for the application. This means there only needs to be 
one copy of the dll, and no change needs to be made to the application. 
However the code that the AT uses to force IA2 to be set up in the 
application could be more complex than it needs to be, plus its another 
lot of injection that doesn't really have to happen. Note that for any 
process the AT wants to access, it must first inject and set up IA2, 
before it can then in its own process access IA2 from the application. 
In my opinion this is rather inefficient and a lot more work than it has 
to be. However I can also see how changes to applications can also be 

I have tested the IA2 setup code in both NVDA, and by injection, 
firefox3, and the code definitely works; ia2 dll does not have to be 
registered. However I must point out that  the change I made to NVDA was 
very hackish, and it rode on the back of some virtualBuffer code, so I 
only got IA2 support when NVDA rendered documents.  My point is that 
although I know the method works, I would certainly be happyer seeing 
each application  set up IA2 itself.

I think this is an issue we need to talk about in great detail.

Many people have asked me why does NVDA not totally go in-process (which 
would fix the IA2 issue). The answer is: we may one day. But if we do it 
would be such a massive change that the project would not be called 
NVDA, it would also no longer be written in Python. But, the fact still 
remains that not just NVDA is affected by this problem.

What are peoples thoughts on this issue?

Does anyone know of any ways we can improve the code, or completely 
remove the need for the application having to setup IA2 in its own process?


Pete Brunet wrote:
> Mick, I couldn't find anything like CoRegisterPS or CoRegisterProxyStub
> that Glen mentioned during the IA2 panel.
> I found DllRegisterServer and the REGISTER_PROXY_DLL macro but haven't
> taken the time to read the docs to get a feel for if that would be of
> any help.
> I also wonder if you can just directly add keys to the registry using
> RegCreateKeyEx, RegSetValueEx, RegCloseKey?
> I also wonder about the proxy DLL. I searched the registry with regedit
> and found one entry
> HKEY_CLASSES_ROOT\CLSID\{01C20F2B-3DD2-400F-949F-AD00BDAB1D41}\InProcServer32
> where the key name is (Default) and the value is
> C:\WINDOWS\system32\IAccessible2Proxy.dll and the GUID in the key name
> is the one for IAccessibleHyperLink. But why don't I see the GUIDs for
> all the other interfaces?
> Do you know of a tool that could inspect the proxy DLL and dump out the
> interface names, method names, and method signatures?
> *Pete Brunet*
> IBM Accessibility Architecture and Development
> 11501 Burnet Road, MS 9022E004, Austin, TX 78758
> Voice: (512) 838-4594, Cell: (512) 689-4155
> Ionosphere: WS4G

More information about the Accessibility-ia2 mailing list