Skip to content

Commit 9a7c58c

Browse files
authored
Merge ea770dd into 3f89b60
2 parents 3f89b60 + ea770dd commit 9a7c58c

18 files changed

Lines changed: 165 additions & 102 deletions

devDocs/deprecations.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ def __getattr__(attrName: str) -> Any:
1717
# Note: this should only log in situations where it will not be excessively noisy.
1818
log.warning(
1919
"Importing deprecatedSymbolName from here is deprecated. "
20-
"Import X instead and do Y. "
20+
"Import X instead and do Y. ",
21+
# Include stack info so testers can report warning to add-on author.
22+
stack_info=True,
2123
)
2224
# Ensure the API of deprecatedSymbolNameReplacement is the same as the deprecated symbol.
2325
return deprecatedSymbolNameReplacement
@@ -69,4 +71,3 @@ Any API breaking changes such as deprecations marked for removal should be comme
6971

7072
## Announcements
7173
Deprecations should be announced via the [NVDA API mailing list](https://groups.google.com/a/nvaccess.org/g/nvda-api/about).
72-

source/NVDAHelper.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
import globalVars
3131
from logHandler import log
3232
import NVDAState
33-
from utils.security import _isLockScreenModeActive
33+
from utils.security import isLockScreenModeActive
3434

3535
versionedLibPath = os.path.join(globalVars.appDir, 'lib')
3636
versionedLibARM64Path = os.path.join(globalVars.appDir, 'libArm64')
@@ -460,7 +460,7 @@ def nvdaControllerInternal_installAddonPackageFromPath(addonPath):
460460
if globalVars.appArgs.secure:
461461
log.debugWarning("Unable to install add-on into secure copy of NVDA.")
462462
return
463-
if _isLockScreenModeActive():
463+
if isLockScreenModeActive():
464464
log.debugWarning("Unable to install add-on while Windows is locked.")
465465
return
466466
import wx
@@ -475,7 +475,7 @@ def nvdaControllerInternal_openConfigDirectory():
475475
if globalVars.appArgs.secure:
476476
log.debugWarning("Unable to open user config directory for secure copy of NVDA.")
477477
return
478-
if _isLockScreenModeActive():
478+
if isLockScreenModeActive():
479479
log.debugWarning("Unable to open user config directory while Windows is locked.")
480480
return
481481
import systemUtils

source/NVDAObjects/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
import brailleInput
4343
import locationHelper
4444
import aria
45-
from winAPI.sessionTracking import _isLockScreenModeActive
45+
from winAPI.sessionTracking import isLockScreenModeActive
4646

4747

4848
class NVDAObjectTextInfo(textInfos.offsets.OffsetsTextInfo):
@@ -188,7 +188,7 @@ def _insertLockScreenObject(self, clsList: typing.List["NVDAObject"]) -> None:
188188
Inserts LockScreenObject to the start of the clsList if Windows is locked.
189189
"""
190190
from .lockscreen import LockScreenObject
191-
if _isLockScreenModeActive():
191+
if isLockScreenModeActive():
192192
# This must be resolved first to prevent object navigation outside of the lockscreen.
193193
clsList.insert(0, LockScreenObject)
194194

@@ -1529,6 +1529,6 @@ def getSelectedItemsCount(self,maxCount=2):
15291529
isBelowLockScreen: bool
15301530

15311531
def _get_isBelowLockScreen(self) -> bool:
1532-
if not _isLockScreenModeActive():
1532+
if not isLockScreenModeActive():
15331533
return False
15341534
return _isObjectBelowLockScreen(self)

source/NVDAState.py

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import os
77
import sys
88
import time
9+
import winreg
910

1011
import globalVars
1112

@@ -145,11 +146,11 @@ class _TrackNVDAInitialization:
145146
regardless of lock state.
146147
Security checks may cause the desktop object to not be set if NVDA starts on the lock screen.
147148
As such, during initialization, NVDA should behave as if Windows is unlocked,
148-
i.e. winAPI.sessionTracking._isLockScreenModeActive should return False.
149+
i.e. winAPI.sessionTracking.isLockScreenModeActive should return False.
149150
"""
150151

151152
_isNVDAInitialized = False
152-
"""When False, _isLockScreenModeActive is forced to return False.
153+
"""When False, isLockScreenModeActive is forced to return False.
153154
"""
154155

155156
@staticmethod
@@ -160,3 +161,38 @@ def markInitializationComplete():
160161
@staticmethod
161162
def isInitializationComplete() -> bool:
162163
return _TrackNVDAInitialization._isNVDAInitialized
164+
165+
166+
def _forceSecureModeEnabled() -> bool:
167+
from config import RegistryKey
168+
try:
169+
k = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, RegistryKey.NVDA.value)
170+
return bool(winreg.QueryValueEx(k, RegistryKey.FORCE_SECURE_MODE_SUBKEY.value)[0])
171+
except WindowsError:
172+
# Expected state by default, forceSecureMode parameter not set
173+
return False
174+
175+
176+
def _serviceDebugEnabled() -> bool:
177+
from config import RegistryKey
178+
try:
179+
k = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, RegistryKey.NVDA.value)
180+
return bool(winreg.QueryValueEx(k, RegistryKey.SERVICE_DEBUG_SUBKEY.value)[0])
181+
except WindowsError:
182+
# Expected state by default, serviceDebug parameter not set
183+
return False
184+
185+
186+
def _configInLocalAppDataEnabled() -> bool:
187+
from config import RegistryKey
188+
from logHandler import log
189+
190+
try:
191+
k = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, RegistryKey.NVDA.value)
192+
return bool(winreg.QueryValueEx(k, RegistryKey.CONFIG_IN_LOCAL_APPDATA_SUBKEY.value)[0])
193+
except FileNotFoundError:
194+
log.debug("Installed user config is not in local app data")
195+
return False
196+
except WindowsError:
197+
# Expected state by default, configInLocalAppData parameter not set
198+
return False

source/appModules/lockapp.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@
2121
from NVDAObjects.UIA import UIA
2222
import NVDAState
2323
from utils.security import getSafeScripts
24-
from winAPI.sessionTracking import _isLockScreenModeActive
24+
from winAPI.sessionTracking import isLockScreenModeActive
2525

2626
"""App module for the Windows 10 and 11 lock screen.
2727
2828
The lock screen allows other windows to be opened, so security related functions
2929
are done at a higher level than the lockapp app module.
30-
Refer to usages of `winAPI.sessionTracking._isLockScreenModeActive`.
30+
Refer to usages of `winAPI.sessionTracking.isLockScreenModeActive`.
3131
"""
3232

3333

@@ -60,7 +60,7 @@ def chooseNVDAObjectOverlayClasses(
6060
if isinstance(obj,UIA) and obj.role==controlTypes.Role.PANE and obj.UIAElement.cachedClassName=="LockAppContainer":
6161
clsList.insert(0,LockAppContainer)
6262

63-
if not _isLockScreenModeActive():
63+
if not isLockScreenModeActive():
6464
log.debugWarning(
6565
"LockApp is being initialized but NVDA does not expect Windows to be locked. "
6666
"DynamicNVDAObjectType may have failed to apply LockScreenObject. "

source/brailleViewer/brailleViewerGui.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import fonts
1818
import inputCore
1919
import gui.contextHelp
20-
from utils.security import _isLockScreenModeActive, post_sessionLockStateChanged
20+
from utils.security import isLockScreenModeActive, post_sessionLockStateChanged
2121

2222
BRAILLE_UNICODE_PATTERNS_START = 0x2800
2323
BRAILLE_SPACE_CHARACTER = chr(BRAILLE_UNICODE_PATTERNS_START)
@@ -398,7 +398,7 @@ def _createControls(self, sizer: wx.Sizer, parent: wx.Control) -> None:
398398
self._shouldShowOnStartupCheckBox.SetValue(config.conf["brailleViewer"]["showBrailleViewerAtStartup"])
399399
self._shouldShowOnStartupCheckBox.Bind(wx.EVT_CHECKBOX, self._onShouldShowOnStartupChanged)
400400
optionsSizer.Add(self._shouldShowOnStartupCheckBox)
401-
if _isLockScreenModeActive():
401+
if isLockScreenModeActive():
402402
self._shouldShowOnStartupCheckBox.Disable()
403403

404404
# Translators: The label for a setting in the braille viewer that controls
@@ -415,11 +415,11 @@ def _createControls(self, sizer: wx.Sizer, parent: wx.Control) -> None:
415415
sizer.Add(optionsSizer, flag=wx.EXPAND | wx.TOP, border=5)
416416

417417
def _onShouldShowOnStartupChanged(self, evt: wx.CommandEvent):
418-
if not _isLockScreenModeActive():
418+
if not isLockScreenModeActive():
419419
config.conf["brailleViewer"]["showBrailleViewerAtStartup"] = self._shouldShowOnStartupCheckBox.IsChecked()
420420

421421
def _onShouldHoverRouteToCellCheckBoxChanged(self, evt: wx.CommandEvent):
422-
if not _isLockScreenModeActive():
422+
if not isLockScreenModeActive():
423423
config.conf["brailleViewer"]["shouldHoverRouteToCell"] = self._shouldHoverRouteToCellCheckBox.IsChecked()
424424
self._updateMouseOverBinding(self._shouldHoverRouteToCellCheckBox.IsChecked())
425425

source/config/__init__.py

Lines changed: 16 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,18 @@ class RegistryKey(str, Enum):
119119
Note that NVDA is a 32-bit application, so on X64 systems,
120120
this will evaluate to `r"SOFTWARE\WOW6432Node\nvda"`
121121
"""
122+
CONFIG_IN_LOCAL_APPDATA_SUBKEY = "configInLocalAppData"
123+
"""
124+
#6864: The name of the subkey stored under RegistryKey.NVDA where the value is stored
125+
which will make an installed NVDA load the user configuration either from the local or from
126+
the roaming application data profile.
127+
The registry value is unset by default.
128+
When setting it manually, a DWORD value is preferred.
129+
A value of 0 will evaluate to loading the configuration from the roaming application data (default).
130+
A value of 1 means loading the configuration from the local application data folder.
131+
"""
132+
FORCE_SECURE_MODE_SUBKEY = "forceSecureMode"
133+
SERVICE_DEBUG_SUBKEY = "serviceDebug"
122134

123135

124136
def isInstalledCopy() -> bool:
@@ -165,42 +177,19 @@ def isInstalledCopy() -> bool:
165177
return False
166178

167179

168-
CONFIG_IN_LOCAL_APPDATA_SUBKEY = "configInLocalAppData"
169-
"""
170-
#6864: The name of the subkey stored under RegistryKey.NVDA where the value is stored
171-
which will make an installed NVDA load the user configuration either from the local or from
172-
the roaming application data profile.
173-
The registry value is unset by default.
174-
When setting it manually, a DWORD value is preferred.
175-
A value of 0 will evaluate to loading the configuration from the roaming application data (default).
176-
A value of 1 means loading the configuration from the local application data folder.
177-
"""
178-
179-
180180
def getInstalledUserConfigPath() -> Optional[str]:
181181
try:
182-
k = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, RegistryKey.NVDA.value)
182+
winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, RegistryKey.NVDA.value)
183183
except FileNotFoundError:
184184
log.debug("Could not find nvda registry key, NVDA is not currently installed")
185185
return None
186186
except WindowsError:
187187
log.error("Could not open nvda registry key", exc_info=True)
188188
return None
189189

190-
try:
191-
configInLocalAppData = bool(winreg.QueryValueEx(k, CONFIG_IN_LOCAL_APPDATA_SUBKEY)[0])
192-
except FileNotFoundError:
193-
log.debug("Installed user config is not in local app data")
194-
configInLocalAppData = False
195-
except WindowsError:
196-
log.error(
197-
f"Could not query if user config in local app data {CONFIG_IN_LOCAL_APPDATA_SUBKEY}",
198-
exc_info=True
199-
)
200-
configInLocalAppData = False
201-
configParent = shlobj.SHGetKnownFolderPath(
202-
shlobj.FolderId.LOCAL_APP_DATA if configInLocalAppData else shlobj.FolderId.ROAMING_APP_DATA
203-
)
190+
appDataFolder = shlobj.FolderId.LOCAL_APP_DATA if NVDAState._configInLocalAppDataEnabled() else shlobj.FolderId.ROAMING_APP_DATA
191+
192+
configParent = shlobj.SHGetKnownFolderPath(appDataFolder)
204193
try:
205194
return os.path.join(configParent, "nvda")
206195
except WindowsError:

source/globalVars.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,13 @@ class DefaultAppArgs(argparse.Namespace):
4848
When this is True, NVDA is running in secure mode.
4949
This is set to True when NVDA starts with the --secure parameter.
5050
This is also set to True when NVDA is running on a secure screen
51-
(systemUtils._isSecureDesktop() returns True)
51+
(systemUtils.isRunningOnSecureDesktop() returns True)
5252
and the serviceDebug parameter is not set.
53+
This is forced to true if the forceSecureMode parameter is set.
5354
5455
For more information, refer to devDocs/technicalDesignOverview.md 'Logging in secure mode'
5556
and the following userGuide sections:
56-
- SystemWideParameters (information on the serviceDebug parameter)
57+
- SystemWideParameters (information on the serviceDebug and forceSecureMode parameters)
5758
- SecureMode and SecureScreens
5859
"""
5960
disableAddons: bool = False

source/installer.py

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,27 @@
2222
import COMRegistrationFixes
2323
import winKernel
2424
from typing import (
25+
Any,
2526
Dict,
2627
Union,
2728
)
29+
import NVDAState
2830
from NVDAState import WritePaths
2931

32+
33+
def __getattr__(attrName: str) -> Any:
34+
"""Module level `__getattr__` used to preserve backward compatibility."""
35+
if attrName == "CONFIG_IN_LOCAL_APPDATA_SUBKEY" and NVDAState._allowDeprecatedAPI():
36+
# Note: this should only log in situations where it will not be excessively noisy.
37+
log.warning(
38+
"Importing CONFIG_IN_LOCAL_APPDATA_SUBKEY from here is deprecated. "
39+
"Instead use config.RegistryKey.CONFIG_IN_LOCAL_APPDATA_SUBKEY. ",
40+
stack_info=True,
41+
)
42+
return config.RegistryKey.CONFIG_IN_LOCAL_APPDATA_SUBKEY.value
43+
raise AttributeError(f"module {repr(__name__)} has no attribute {repr(attrName)}")
44+
45+
3046
_wsh=None
3147
def _getWSH():
3248
global _wsh
@@ -298,7 +314,21 @@ def registerInstallation(
298314
with winreg.CreateKeyEx(winreg.HKEY_LOCAL_MACHINE, config.RegistryKey.NVDA.value, 0, winreg.KEY_WRITE) as k:
299315
winreg.SetValueEx(k,"startMenuFolder",None,winreg.REG_SZ,startMenuFolder)
300316
if configInLocalAppData:
301-
winreg.SetValueEx(k,config.CONFIG_IN_LOCAL_APPDATA_SUBKEY,None,winreg.REG_DWORD,int(configInLocalAppData))
317+
winreg.SetValueEx(
318+
k,
319+
config.RegistryKey.CONFIG_IN_LOCAL_APPDATA_SUBKEY.value,
320+
None,
321+
winreg.REG_DWORD,
322+
int(configInLocalAppData)
323+
)
324+
if NVDAState._forceSecureModeEnabled():
325+
winreg.SetValueEx(
326+
k,
327+
config.RegistryKey.FORCE_SECURE_MODE_SUBKEY.value,
328+
None,
329+
winreg.REG_DWORD,
330+
1
331+
)
302332
registerEaseOfAccess(installDir)
303333
if startOnLogonScreen is not None:
304334
config._setStartOnLogonScreen(startOnLogonScreen)
@@ -605,13 +635,9 @@ def tryCopyFile(sourceFilePath,destFilePath):
605635
errorCode = ctypes.GetLastError()
606636
raise OSError("Unable to copy file %s to %s, error %d"%(sourceFilePath,destFilePath,errorCode))
607637

608-
def install(shouldCreateDesktopShortcut=True,shouldRunAtLogon=True):
638+
639+
def install(shouldCreateDesktopShortcut: bool = True, shouldRunAtLogon: bool = True):
609640
prevInstallPath=getInstallPath(noDefault=True)
610-
try:
611-
k = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, config.RegistryKey.NVDA.value)
612-
configInLocalAppData = bool(winreg.QueryValueEx(k, config.CONFIG_IN_LOCAL_APPDATA_SUBKEY)[0])
613-
except WindowsError:
614-
configInLocalAppData = False
615641
unregisterInstallation(keepDesktopShortcut=shouldCreateDesktopShortcut)
616642
installDir=defaultInstallPath
617643
startMenuFolder=defaultStartMenuFolder
@@ -642,7 +668,7 @@ def install(shouldCreateDesktopShortcut=True,shouldRunAtLogon=True):
642668
startMenuFolder,
643669
shouldCreateDesktopShortcut,
644670
shouldRunAtLogon,
645-
configInLocalAppData
671+
NVDAState._configInLocalAppDataEnabled()
646672
)
647673
COMRegistrationFixes.fixCOMRegistrations()
648674

source/nvda.pyw

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,8 @@ elif globalVars.appArgs.check_running:
276276

277277

278278
# Suppress E402 (module level import not at top of file)
279-
from systemUtils import _getDesktopName, _isSecureDesktop # noqa: E402
279+
from utils.security import isRunningOnSecureDesktop # noqa: E402
280+
from systemUtils import _getDesktopName # noqa: E402
280281
# Ensure multiple instances are not fully started by using a mutex
281282
desktopName = _getDesktopName()
282283
_log.info(f"DesktopName: {desktopName}")
@@ -355,20 +356,12 @@ if mutex is None:
355356
sys.exit(1)
356357

357358

358-
def _serviceDebugEnabled() -> bool:
359-
import winreg
360-
try:
361-
k = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\NVDA")
362-
if winreg.QueryValueEx(k, "serviceDebug")[0]:
363-
return True
364-
except WindowsError:
365-
# Expected state by default, serviceDebug parameter not set
366-
pass
367-
return False
359+
if NVDAState._forceSecureModeEnabled():
360+
globalVars.appArgs.secure = True
368361

369362

370-
if _isSecureDesktop():
371-
if not _serviceDebugEnabled():
363+
if isRunningOnSecureDesktop():
364+
if not NVDAState._serviceDebugEnabled():
372365
globalVars.appArgs.secure = True
373366
globalVars.appArgs.changeScreenReaderFlag = False
374367
globalVars.appArgs.minimal = True
@@ -398,7 +391,7 @@ if not ctypes.windll.user32.ChangeWindowMessageFilter(winUser.WM_QUIT, winUser.M
398391
raise winUser.WinError()
399392
# Make this the last application to be shut down and don't display a retry dialog box.
400393
winKernel.SetProcessShutdownParameters(0x100, winKernel.SHUTDOWN_NORETRY)
401-
if not _isSecureDesktop() and not config.isAppX:
394+
if not isRunningOnSecureDesktop() and not config.isAppX:
402395
import easeOfAccess
403396
easeOfAccess.notify(3)
404397
try:
@@ -408,7 +401,7 @@ except:
408401
log.critical("core failure",exc_info=True)
409402
sys.exit(1)
410403
finally:
411-
if not _isSecureDesktop() and not config.isAppX:
404+
if not isRunningOnSecureDesktop() and not config.isAppX:
412405
easeOfAccess.notify(2)
413406
if globalVars.appArgs.changeScreenReaderFlag:
414407
winUser.setSystemScreenReaderFlag(False)

0 commit comments

Comments
 (0)