OSDN Git Service

A bit of a re-write to nvdahelper injection and rpc code to allow NVDA access to...
authorMichael Curran <mick@kulgan.net>
Mon, 16 Apr 2012 01:24:15 +0000 (11:24 +1000)
committerMichael Curran <mick@kulgan.net>
Mon, 16 Apr 2012 01:24:15 +0000 (11:24 +1000)
commit686ea7cd35b96602078bdf52459089274ac5331d
tree454f6824f0ac47c34d0946cdf9e670251fca25c6
parent2567d7e5ce83cfa28c1802bf2c0b98b91aec5911
A bit of a re-write to nvdahelper injection and rpc code to allow NVDA access to inproc rpc interfaces such as virtualBuffers hosted in an appContainer process (e.g. metro app). Assuming NVDA has the UIAccess privilidge, virtualBuffers are now available in metro apps such as Store.
Specific changes:
   * On win8 nvdaHelperLocal registers the nvdaController and nvdaControllerInternal interfaces using the new RpcServerRegisterIf3, allowing the use of a security descriptor which specifically allows access from AppContainer integrity processes. However as the security descriptor overrides any defaults, it also for now allows access from any authenticated users  -- this could be tightened up.
* nvdaInprocUtils now has two new methods: registerNVDAProcess and unregisterNVDAProcess, plus an rundown function for the context handle registerNVDAProcess provides. When injection is all initialized, NVDA can call registerNVDAprocess and when it wants the inproc code to terminate it can call unregisterNVDAProcess, or just break the connection or exit. registerNVDAProcess sets an nvdaUnregisteredEvent to nonSignaled, which the inproc code uses to wait on. UnregisterNVDAProcess (also called by the rundown if the connection breaks) sets this event to signaled to instruct the inproc code to terminate.
* nvdaHelperRemote: remove the injectionDoneEvent and any code that waited on it or the NVDA process. Its no longer needed. Note that this did not work in AppContainer processes anyway unless a specific security descriptor was set for both the NVDA process and the injectionDoneEvent.
* nvdaHelperRemote: When registering its RPC interfaces (nvdaInprocUtils, displayModel and VBuf), use RpcUseProtSeq rather than RpcUseProtSeqEp so as to listen on a dynamic endpoint rather than a well-known one. AppContainer processes mangled the endpoint name anyway. Publish correct dynamic endpoints for each interface along with a generated UUID specific to this instance of the inproc code, using RpcEpRegister, so that NVDA can locate this processes endpoint by using the interface and generated UUID. Finally also call a new nvdaControllerInternal method: requestRegistration to ask NVDA to register with this inproc code before the call returns.
* nvdaHelperLocal: rename createConnection to createRemoteBindingHandle (which is more true) and also set a security descriptor on the created binding handle to allow an AppContainer server to talk back to this client -- could be tightened up. createRemoteBindingHandle also now takes a uuid parameter which it uses when creating the binding handle so its able to locate the correct endpoint.
* nvdaControllerInternal: add a new requestRegistration method, which takes a UUID string which can be used to locate the caller's own inproc rpc interfaces. The implementation of requestRegistration uses the UUID to create a bindingHandle for remote access to the inproc code using createRemoteBindingHandle, storing it on the appModule which it creates if necessary. It also calls registerNVDAProcess so as to retreave a context handle from the inproc code that if broken will force the inproc code to terminate. This is also stored on the appModule.
* AppModule.terminate: If a registrationhandle exists, destroy it with rpcSsDestroyClientContext. If a bindingHandle exists then free it with RpcBindingFree. Destroying both of these is enough to ensure the connection with the inproc code breaks and therefore the rundown for the registration will run and inproc code will be terminated. This is safer than specifically calling unregisterNVDAProcess which could freee or may fail if the remote process is busy or shutting down or is dead etc.
* core.initialize: initialize appModuleHandler before nvdaHelper as nvdahelper.nvdaControllerInternal_requestRegistration, which can happen quite quick, needs the ability to create an appModule.
17 files changed:
nvdaHelper/interfaces/nvdaControllerInternal/nvdaControllerInternal.acf
nvdaHelper/interfaces/nvdaControllerInternal/nvdaControllerInternal.idl
nvdaHelper/interfaces/nvdaInProcUtils/nvdaInProcUtils.acf
nvdaHelper/interfaces/nvdaInProcUtils/nvdaInProcUtils.idl
nvdaHelper/local/nvdaControllerInternal.c
nvdaHelper/local/nvdaHelperLocal.cpp
nvdaHelper/local/nvdaHelperLocal.def
nvdaHelper/local/nvdaHelperLocal.h
nvdaHelper/local/rpcSrv.cpp
nvdaHelper/local/sconscript
nvdaHelper/remote/inProcess.cpp
nvdaHelper/remote/injection.cpp
nvdaHelper/remote/rpcSrv.cpp
nvdaHelper/remote/rpcSrv.h
source/NVDAHelper.py
source/appModuleHandler.py
source/core.py