Permalink
Browse files

In-process components on ARM64 (#9216)

* Upgrade SCons to version 3.0.4.

This required some tweaks to the sconscripts for ISimpleDOM and MathPlayer.
We copy the idl file into the build directory ourselves, but it depends on other files.
It seems SCons no longer scans for dependencies in files we copy ourselves.
Thus, we must explicitly declare those dependencies.

* Build and install in-process components for ARM64.

These are placed in a new libArm64 directory (alongside lib and lib64).
MinHook doesn't support ARM64, so disable MinHook and everything that depends on it (notably displayModel).

* Start nvdaHelperRemoteLoader appropriately on ARM64.

* Fix AppModule.is64BitProcess for ARM64.

Previously, it always returned True, even for 32 bit processes.
On ARM64, isWow64Process always returns False.
We must instead use IsWow64Process2 where supported.

* Update readme to list the additional Visual Studio components we now require.

* Update what's new.
  • Loading branch information...
jcsteh authored and michaelDCurran committed Jan 31, 2019
1 parent 504da10 commit ec49fa71b1fce97e0e84c47ab91d475a2e538007
Submodule scons updated from 6a72c4 to 73b2c0
@@ -17,8 +17,10 @@ Import('env')
env['MIDLCOM']=env['MIDLCOM'][:-6]

# Copy some secondary IDL files included by ISimpleDOMNode.idl
env.Command("ISimpleDOMText.idl","#/miscDeps/include/ISimpleDOM/ISimpleDOMText.idl",Copy("$TARGET","$SOURCE"))
env.Command("ISimpleDOMDocument.idl","#/miscDeps/include/ISimpleDOM/ISimpleDOMDocument.idl",Copy("$TARGET","$SOURCE"))
idlDeps = [
env.Command("ISimpleDOMText.idl","#/miscDeps/include/ISimpleDOM/ISimpleDOMText.idl",Copy("$TARGET","$SOURCE")),
env.Command("ISimpleDOMDocument.idl","#/miscDeps/include/ISimpleDOM/ISimpleDOMDocument.idl",Copy("$TARGET","$SOURCE")),
]
# copy ISimpleDOMNode.idl but changing imports of the secondary files to #includes
# This is necessary as midl will not build secondary header files. this way the primary header file will contain all secondary header file content
idlFile=env.Substfile(
@@ -28,6 +30,9 @@ idlFile=env.Substfile(
'import "ISimpleDOM':'#include "ISimpleDOM',
}
)
# SCons doesn't scan the file we just created,
# so we must explicitly declare its dependencies.
env.Depends(idlFile, idlDeps)

tlbFile,headerFile,iidSourceFile,proxySourceFile,dlldataSourceFile=env.TypeLibrary(
source=idlFile,
@@ -105,15 +105,24 @@ if 'analyze' in debug:
env.Append(CXXFLAGS=['/EHsc'])

env.Append(CPPPATH=['#/include','#/miscDeps/include',Dir('.').abspath])
if TARGET_ARCH == "arm64":
subsystem = "/subsystem:windows,6.02"
else:
subsystem = "/subsystem:windows,6.01"
env.Append(
LINKFLAGS=[
'/incremental:no',
'/WX',
'/subsystem:windows,6.01',
subsystem,
]
)
env.Append(LINKFLAGS='/release') #We always want a checksum in the header
env.Append(MIDLFLAGS='/x64' if TARGET_ARCH=='x86_64' else '/win32')
if TARGET_ARCH == 'x86_64':
env.Append(MIDLFLAGS='/x64')
elif TARGET_ARCH == 'arm64':
env.Append(MIDLFLAGS='/arm64')
else:
env.Append(MIDLFLAGS='/win32')

if not release:
env.Append(CCFLAGS=['/Od'])
@@ -185,19 +194,20 @@ if signExec:
env.AddPostAction(clientLib[0],[signExec])
env.Install(clientInstallDir,clientLib)

minHookLib=env.SConscript('minHook/sconscript')
Export('minHookLib')
if signExec:
env.AddPostAction(minHookLib[0],[signExec])
env.Install(libInstallDir,minHookLib)
if TARGET_ARCH != 'arm64':
minHookLib=env.SConscript('minHook/sconscript')
Export('minHookLib')
if signExec:
env.AddPostAction(minHookLib[0],[signExec])
env.Install(libInstallDir,minHookLib)

remoteLib=env.SConscript('remote/sconscript')
Export('remoteLib')
if signExec:
env.AddPostAction(remoteLib[0],[signExec])
env.Install(libInstallDir,remoteLib)

if TARGET_ARCH=='x86_64':
if TARGET_ARCH in ('x86_64', 'arm64'):
remoteLoaderProgram=env.SConscript('remoteLoader/sconscript')
if signExec:
env.AddPostAction(remoteLoaderProgram,[signExec])
@@ -14,8 +14,11 @@

Import('env')

env.Command("MathSpeechEnums.idl","#/miscDeps/include/mathPlayer/MathSpeechEnums.idl",Copy("$TARGET","$SOURCE"))
idlDep = env.Command("MathSpeechEnums.idl","#/miscDeps/include/mathPlayer/MathSpeechEnums.idl",Copy("$TARGET","$SOURCE"))
idlFile=env.Command("mathPlayerDLL.idl","#/miscDeps/include/mathPlayer/mathPlayerDLL.idl",Copy("$TARGET","$SOURCE"))
# SCons doesn't scan the file we just created,
# so we must explicitly declare its dependencies.
env.Depends(idlFile, idlDep)

tlbFile,headerFile,iidSourceFile,proxySourceFile,dlldataSourceFile=env.TypeLibrary(
source=idlFile,
@@ -50,11 +50,15 @@ void inProcess_initialize() {
TSF_inProcess_initialize();
IME_inProcess_initialize();
winword_inProcess_initialize();
#ifndef _M_ARM64
gdiHooks_inProcess_initialize();
#endif
}

void inProcess_terminate() {
#ifndef _M_ARM64
gdiHooks_inProcess_terminate();
#endif
IME_inProcess_terminate();
TSF_inProcess_terminate();
winword_inProcess_terminate();
@@ -167,17 +167,21 @@ DWORD WINAPI inprocMgrThreadFunc(LPVOID data) {
if(inprocWinEventHookID==0) {
LOG_ERROR(L"SetWinEventHook failed");
}
#ifndef _M_ARM64
//Initialize API hooking
apiHook_initialize();
//Hook SetWindowsHookExA so that we can juggle hooks around a bit.
//Fixes #2411
real_SetWindowsHookExA=apiHook_hookFunction_safe("USER32.dll",SetWindowsHookExA,fake_SetWindowsHookExA);
//Fore secure mode NVDA process, hook OpenClipboard to disable usage of the clipboard
if(isSecureModeNVDAProcess) real_OpenClipboard=apiHook_hookFunction_safe("USER32.dll",OpenClipboard,fake_OpenClipboard);
if(isSecureModeNVDAProcess) real_OpenClipboard=apiHook_hookFunction_safe("USER32.dll",OpenClipboard,fake_OpenClipboard);
#endif // #ifndef _M_ARM64
//Initialize in-process subsystems
inProcess_initialize();
#ifndef _M_ARM64
//Enable all registered API hooks
apiHook_enableHooks();
#endif
//Initialize our rpc server interfaces and request registration with NVDA
rpcSrv_initialize();
//Notify injection_winEventCallback (who started our thread) that we're past initialization
@@ -207,8 +211,10 @@ if(isSecureModeNVDAProcess) real_OpenClipboard=apiHook_hookFunction_safe("USER32
#endif
//Terminate our RPC server interfaces
rpcSrv_terminate();
#ifndef _M_ARM64
//Unregister and terminate API hooks
apiHook_terminate();
#endif
//Terminate all in-process subsystems.
inProcess_terminate();
//Unregister any windows hooks registered so far
@@ -375,8 +381,10 @@ BOOL WINAPI DllMain(HINSTANCE hModule,DWORD reason,LPVOID lpReserved) {
#ifndef NDEBUG
Beep(2500,75);
#endif
#ifndef _M_ARM64
//Unregister and terminate API hooks
apiHook_terminate();
#endif
//Unregister any current windows hooks
killRunningWindowsHooks();
//Unregister winEvents for this process
@@ -20,7 +20,9 @@ This license can be found at:
#include "nvdaControllerInternal.h"
#include <common/log.h>
#include "vbufRemote.h"
#ifndef _M_ARM64
#include "displayModelRemote.h"
#endif
#include "NvdaInProcUtils.h"
#include "nvdaControllerInternal.h"
#include "rpcSrv.h"
@@ -29,7 +31,9 @@ typedef RPC_STATUS(RPC_ENTRY *RpcServerRegisterIf3_functype)(RPC_IF_HANDLE,UUID

RPC_IF_HANDLE availableInterfaces[]={
nvdaInProcUtils_NvdaInProcUtils_v1_0_s_ifspec,
#ifndef _M_ARM64
displayModelRemote_DisplayModel_v1_0_s_ifspec,
#endif
VBufRemote_VBuf_v2_0_s_ifspec,
};

@@ -60,15 +60,16 @@ vbufRPCHeader,vbufRPCServerSource=env.MSRPCStubs(
MSRPCStubs_prefix="VBufRemote_",
)

displayModelRPCHeader,displayModelRPCServerSource=env.MSRPCStubs(
target="./displayModelRemote",
source=[
"../interfaces/displayModel/displayModel.idl",
"../interfaces/displayModel/displayModel.acf",
],
MSRPCStubs_noClient=True,
MSRPCStubs_prefix="displayModelRemote_",
)
if env["TARGET_ARCH"] != 'arm64':
displayModelRPCHeader,displayModelRPCServerSource=env.MSRPCStubs(
target="./displayModelRemote",
source=[
"../interfaces/displayModel/displayModel.idl",
"../interfaces/displayModel/displayModel.acf",
],
MSRPCStubs_noClient=True,
MSRPCStubs_prefix="displayModelRemote_",
)

nvdaInProcUtilsRPCHeader,nvdaInProcUtilsRPCServerSource=env.MSRPCStubs(
target="./nvdaInProcUtils",
@@ -82,55 +83,61 @@ nvdaInProcUtilsRPCHeader,nvdaInProcUtilsRPCServerSource=env.MSRPCStubs(

ia2utilsObj=env.Object("./ia2utils","../common/ia2utils.cpp")

remoteLib=env.SharedLibrary(
target="nvdaHelperRemote",
source=[
env['projectResFile'],
"injection.cpp",
"log.cpp",
"inProcess.cpp",
"apiHook.cpp",
"inputLangChange.cpp",
"typedCharacter.cpp",
"ime.cpp",
"tsf.cpp",
"COMProxyRegistration.cpp",
"ia2Support.cpp",
"ia2LiveRegions.cpp",
ia2utilsObj,
env.Object('_ia2_i',ia2RPCStubs[3]),
"rpcSrv.cpp",
"vbufRemote.cpp",
vbufRPCServerSource,
winIPCUtilsObj,
controllerRPCClientSource,
controllerInternalRPCClientSource,
"sysListView32.cpp",
"winword.cpp",
"WinWord/Fields.cpp",
"outlook.cpp",
source = [
env['projectResFile'],
"injection.cpp",
"log.cpp",
"inProcess.cpp",
"apiHook.cpp",
"inputLangChange.cpp",
"typedCharacter.cpp",
"ime.cpp",
"tsf.cpp",
"COMProxyRegistration.cpp",
"ia2Support.cpp",
"ia2LiveRegions.cpp",
ia2utilsObj,
env.Object('_ia2_i',ia2RPCStubs[3]),
"rpcSrv.cpp",
"vbufRemote.cpp",
vbufRPCServerSource,
winIPCUtilsObj,
controllerRPCClientSource,
controllerInternalRPCClientSource,
"sysListView32.cpp",
"winword.cpp",
"WinWord/Fields.cpp",
"outlook.cpp",
nvdaInProcUtilsRPCServerSource,
"nvdaHelperRemote.def",
vbufBackendLibs,
]
libs = [
"user32",
"ole32",
"rpcrt4",
"shlwapi",
"oleaut32",
"oleacc",
"usp10",
"imm32",
"advapi32",
"version",
"DbgHelp",
]
# MinHook doesn't support ARM64, which means we can't support displayModel on ARM64.
if env["TARGET_ARCH"] != 'arm64':
source.extend((
"gdiHooks.cpp",
"displayModel.cpp",
"displayModelRemote.cpp",
displayModelRPCServerSource,
nvdaInProcUtilsRPCServerSource,
"nvdaHelperRemote.def",
vbufBackendLibs,
],
LIBS=[
"user32",
"gdi32",
"ole32",
"rpcrt4",
"shlwapi",
"oleaut32",
"oleacc",
"usp10",
"imm32",
"advapi32",
"version",
"DbgHelp",
],
))
libs.append("gdi32")
remoteLib=env.SharedLibrary(
target="nvdaHelperRemote",
source=source,
LIBS=libs,
)

Return('remoteLib')
@@ -42,10 +42,13 @@ The following dependencies need to be installed on your system:
On the Workloads tab, in the Windows group:
* Universal Windows Platform Development
* Desktop development with C++
* Then in the Summary list, under Desktop for C++, Optional grouping, ensure the following is selected:
* Then in the Installation details section, under Desktop for C++, Optional grouping, ensure the following are selected:
* VC++ 2017 v141 toolset (x86,x64)
* Windows 10 SDK (10.0.17134.0) for Desktop C++ x86 and x64
* Visual C++ ATL for x86 and x64
* In the Installation details section, under Individual components, ensure the following are selected:
* Visual C++ compilers and libraries for ARM64
* Visual C++ ATL for ARM64


### Git Submodules
@@ -72,7 +75,7 @@ For reference, the following dependencies are included in Git submodules:
* Adobe FlashAccessibility interface typelib
* [txt2tags](http://txt2tags.sourceforge.net/), version 2.5
* [MinHook](https://github.com/RaMMicHaeL/minhook), tagged version 1.2.2
* [SCons](http://www.scons.org/), version 3.0.0, commit 6a72c4de
* [SCons](http://www.scons.org/), version 3.0.4
* brlapi Python bindings, version 0.5.7 or later, distributed with [BRLTTY for Windows](http://brl.thefreecat.org/brltty/), version 4.2-2
* ALVA BC6 generic dll, version 3.0.4.1
* lilli.dll, version 2.1.0.0
@@ -118,6 +118,8 @@ sourceTypelibDir=sourceDir.Dir('typelibs')
Export('sourceTypelibDir')
sourceLibDir64=sourceDir.Dir('lib64')
Export('sourceLibDir64')
sourceLibDirArm64=sourceDir.Dir('libArm64')
Export('sourceLibDirArm64')
buildDir = Dir("build")
outFilePrefix = "nvda{type}_{version}".format(type="" if release else "_snapshot", version=version)
Export('outFilePrefix')
@@ -150,9 +152,11 @@ env['signExec']=signExec
archTools=['default','midl','msrpc']
env32=env.Clone(TARGET_ARCH='x86',tools=archTools)
env64=env.Clone(TARGET_ARCH='x86_64',tools=archTools)
envArm64=env.Clone(TARGET_ARCH='arm64',tools=archTools)
# Hack around odd bug where some tool [after] msvc states that static and shared objects are different
env32['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1
env64['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1
envArm64['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1

env=env32

@@ -170,6 +174,7 @@ resFile=env.RES(target='build/nvda.res',
source=env.Substfile(target='build/nvda.rc', source='nvdaHelper/nvda.rc.subst', SUBST_DICT=projectRCSubstDict))
env32['projectResFile'] = resFile
env64['projectResFile'] = resFile
envArm64['projectResFile'] = resFile

#Fill sourceDir with anything provided for it by miscDeps
env.recursiveCopy(sourceDir,Dir('miscdeps/source'))
@@ -179,6 +184,7 @@ env.SConscript('source/comInterfaces_sconscript',exports=['env'])
#Process nvdaHelper scons files
env32.SConscript('nvdaHelper/archBuild_sconscript',exports={'env':env32,'clientInstallDir':clientDir.Dir('x86'),'libInstallDir':sourceLibDir},variant_dir='build/x86')
env64.SConscript('nvdaHelper/archBuild_sconscript',exports={'env':env64,'clientInstallDir':clientDir.Dir('x64'),'libInstallDir':sourceLibDir64},variant_dir='build/x86_64')
envArm64.SConscript('nvdaHelper/archBuild_sconscript',exports={'env':envArm64,'clientInstallDir':clientDir.Dir('arm64'),'libInstallDir':sourceLibDirArm64},variant_dir='build/arm64')

#Allow all NVDA's gettext po files to be compiled in source/locale
for po in env.Glob(sourceDir.path+'/locale/*/lc_messages/*.po'):
@@ -1,6 +1,6 @@
#NVDAHelper.py
#A part of NonVisual Desktop Access (NVDA)
#Copyright (C) 2008-2018 NV Access Limited, Peter Vagner, Davy Kager
#Copyright (C) 2008-2019 NV Access Limited, Peter Vagner, Davy Kager, Mozilla Corporation
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

@@ -28,7 +28,10 @@
import globalVars

versionedLibPath='lib'
versionedLib64Path='lib64'
if os.environ.get('PROCESSOR_ARCHITEW6432') == 'ARM64':
versionedLib64Path = 'libArm64'
else:
versionedLib64Path = 'lib64'
if getattr(sys,'frozen',None):
# Not running from source. Libraries are in a version-specific directory
versionedLibPath=os.path.join(versionedLibPath,versionInfo.version)
@@ -496,7 +499,7 @@ def initialize():
log.error("Error installing IA2 support")
#Manually start the in-process manager thread for this NVDA main thread now, as a slow system can cause this action to confuse WX
_remoteLib.initInprocManagerThreadIfNeeded()
if os.environ.get('PROCESSOR_ARCHITEW6432')=='AMD64':
if os.environ.get('PROCESSOR_ARCHITEW6432') in ('AMD64', 'ARM64'):
_remoteLoader64=RemoteLoader64()

def terminate():
Oops, something went wrong.

0 comments on commit ec49fa7

Please sign in to comment.