diff --git a/include/scons b/include/scons index 6a72c4de3e9..73b2c02d708 160000 --- a/include/scons +++ b/include/scons @@ -1 +1 @@ -Subproject commit 6a72c4de3e92cae65016578270e6f68e66c4f1e8 +Subproject commit 73b2c02d7088c6d6490fdede8396d88103b00482 diff --git a/nvdaHelper/ISimpleDOM_sconscript b/nvdaHelper/ISimpleDOM_sconscript index 45de6b69cc5..b6ee059060e 100644 --- a/nvdaHelper/ISimpleDOM_sconscript +++ b/nvdaHelper/ISimpleDOM_sconscript @@ -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, diff --git a/nvdaHelper/archBuild_sconscript b/nvdaHelper/archBuild_sconscript index c9dda300b82..111896e13f3 100644 --- a/nvdaHelper/archBuild_sconscript +++ b/nvdaHelper/archBuild_sconscript @@ -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,11 +194,12 @@ 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') @@ -197,7 +207,7 @@ 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]) diff --git a/nvdaHelper/mathPlayer_sconscript b/nvdaHelper/mathPlayer_sconscript index 133e20ade14..9d30149daa3 100644 --- a/nvdaHelper/mathPlayer_sconscript +++ b/nvdaHelper/mathPlayer_sconscript @@ -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, diff --git a/nvdaHelper/remote/inProcess.cpp b/nvdaHelper/remote/inProcess.cpp index a618306be43..051976a9537 100755 --- a/nvdaHelper/remote/inProcess.cpp +++ b/nvdaHelper/remote/inProcess.cpp @@ -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(); diff --git a/nvdaHelper/remote/injection.cpp b/nvdaHelper/remote/injection.cpp index 54f5defbd94..6394404eb91 100644 --- a/nvdaHelper/remote/injection.cpp +++ b/nvdaHelper/remote/injection.cpp @@ -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 diff --git a/nvdaHelper/remote/rpcSrv.cpp b/nvdaHelper/remote/rpcSrv.cpp index 185bebdff3c..7fe728743fb 100755 --- a/nvdaHelper/remote/rpcSrv.cpp +++ b/nvdaHelper/remote/rpcSrv.cpp @@ -20,7 +20,9 @@ This license can be found at: #include "nvdaControllerInternal.h" #include #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, }; diff --git a/nvdaHelper/remote/sconscript b/nvdaHelper/remote/sconscript index 4f16334ee3b..7ad3aadfcb2 100644 --- a/nvdaHelper/remote/sconscript +++ b/nvdaHelper/remote/sconscript @@ -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') diff --git a/readme.md b/readme.md index ec0edbf9c1b..304e6fccd5a 100644 --- a/readme.md +++ b/readme.md @@ -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 diff --git a/sconstruct b/sconstruct index 38b18eeee7e..82107244f35 100755 --- a/sconstruct +++ b/sconstruct @@ -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'): diff --git a/source/NVDAHelper.py b/source/NVDAHelper.py index bc189d7f5d4..830a9cd823f 100755 --- a/source/NVDAHelper.py +++ b/source/NVDAHelper.py @@ -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(): diff --git a/source/appModuleHandler.py b/source/appModuleHandler.py index 1fa98edafc0..52e1afdb7d3 100644 --- a/source/appModuleHandler.py +++ b/source/appModuleHandler.py @@ -1,7 +1,7 @@ # -*- coding: UTF-8 -*- #appModuleHandler.py #A part of NonVisual Desktop Access (NVDA) -#Copyright (C) 2006-2018 NV Access Limited, Peter Vágner, Aleksey Sadovoy, Patrick Zajda, Joseph Lee, Babbage B.V. +#Copyright (C) 2006-2019 NV Access Limited, Peter Vágner, Aleksey Sadovoy, Patrick Zajda, Joseph Lee, Babbage B.V., Mozilla Corporation #This file is covered by the GNU General Public License. #See the file COPYING for more details. @@ -412,11 +412,23 @@ def _get_is64BitProcess(self): # This is 32 bit Windows. self.is64BitProcess = False return False - res = ctypes.wintypes.BOOL() - if ctypes.windll.kernel32.IsWow64Process(self.processHandle, ctypes.byref(res)) == 0: - self.is64BitProcess = False - return False - self.is64BitProcess = not res + try: + # We need IsWow64Process2 to detect WOW64 on ARM64. + processMachine = ctypes.wintypes.USHORT() + if ctypes.windll.kernel32.IsWow64Process2(self.processHandle, + ctypes.byref(processMachine), None) == 0: + self.is64BitProcess = False + return False + # IMAGE_FILE_MACHINE_UNKNOWN if not a WOW64 process. + self.is64BitProcess = processMachine.value == winKernel.IMAGE_FILE_MACHINE_UNKNOWN + except AttributeError: + # IsWow64Process2 is only supported on Windows 10 version 1511 and later. + # Fall back to IsWow64Process. + res = ctypes.wintypes.BOOL() + if ctypes.windll.kernel32.IsWow64Process(self.processHandle, ctypes.byref(res)) == 0: + self.is64BitProcess = False + return False + self.is64BitProcess = not res return self.is64BitProcess def isGoodUIAWindow(self,hwnd): diff --git a/source/setup.py b/source/setup.py index f71e607e4f8..2e0558a8a36 100755 --- a/source/setup.py +++ b/source/setup.py @@ -221,6 +221,7 @@ def getRecursiveDataFiles(dest,source,excludes=()): ("documentation", ['../copying.txt', '../contributors.txt']), ("lib/%s"%version, glob("lib/*.dll")), ("lib64/%s"%version, glob("lib64/*.dll") + glob("lib64/*.exe")), + ("libArm64/%s"%version, glob("libArm64/*.dll") + glob("libArm64/*.exe")), ("waves", glob("waves/*.wav")), ("images", glob("images/*.ico")), ("louis/tables",glob("louis/tables/*")), diff --git a/source/winKernel.py b/source/winKernel.py index 797e29e3a55..2d827078bd5 100644 --- a/source/winKernel.py +++ b/source/winKernel.py @@ -42,6 +42,8 @@ WAIT_OBJECT_0 = 0x00000000L WAIT_TIMEOUT = 0x00000102L WAIT_FAILED = 0xffffffff +# Image file machine constants +IMAGE_FILE_MACHINE_UNKNOWN = 0 def GetStdHandle(handleID): h=kernel32.GetStdHandle(handleID) diff --git a/user_docs/en/changes.t2t b/user_docs/en/changes.t2t index 4e80dda1681..641d84bafa2 100644 --- a/user_docs/en/changes.t2t +++ b/user_docs/en/changes.t2t @@ -16,6 +16,7 @@ What's New in NVDA - This works in Firefox 66 and later. - This does not work for certain list boxes (HTML select controls) in Chrome. - Added the Afrikaans braille table. (#9186) +- Early support for apps such as Mozilla Firefox on computers with ARM64 (e.g. Qualcom Snapdragon) processors. (#9216) == Changes ==