Hey, How did you subscribe to that list? Thanks: Paul
installer source source/NVDAHelpersource/appModules source/config source/gui user_docs/en----- Original Message ----- From: Nimer Jaber <nimerjaber1@xxxxxxxxx To: blind_html@xxxxxxxxxxxxx Date sent: Fri, 15 May 2009 07:11:31 -0600Subject: blind_html Fwd: [Nvda-dev] commit r2928 - in trunk: .
This is exciting!!!
-------- Original Message -------- Subject: [Nvda-dev] commit r2928 - in trunk: . installer sourcesource/NVDAHelper source/appModules source/config source/gui
user_docs/en
Date: Fri, 15 May 2009 07:13:21 +0000 From: NVDA Subversion <svn@xxxxxxxxxxxxxxxxReply-To: News and discussion for NVDA (NonVisual Desktop
Access), a
free and open source screen reader for Microsoft Windows <nvda-dev@xxxxxxxxxxxxxxxxxx To: nvda-dev@xxxxxxxxxxxxxxxxxx
Author: nvda Date: Fri May 15 07:13:17 2009 New Revision: 2928
you log on to Windows. The option is in the General Settings dialog.Log:* new: NVDA can be configured to start automatically after
* new: NVDA can read secure Windows screens such as theWindows logon, control+alt+delete and UAC screens in Windows XP and above. Reading of the Windows logon screen can be configured from the General Settings dialog. (#97)
* fix: On Windows Vista, the NVDA installer now starts NVDAwith normal user privileges when requested to run NVDA on the finish screen.
New misc-deps package, version 2009-05-15-01. Includes newNVDAHelper with bug fixes, new nvVBufLib with bug fixes and optimisations, and NSIS components for secure desktop and UAC support.
Added: trunk/source/NVDAHelper/IA2Support.cpp- copied, changed from r2927,
/trunk/source/NVDAHelper/IA2Support.c
trunk/source/NVDAHelper/hookManager.cpp- copied, changed from r2927,
/trunk/source/NVDAHelper/hookManager.c
trunk/source/NVDAHelper/inputLangChange.cpp- copied, changed from r2927,
/trunk/source/NVDAHelper/inputLangChange.c
trunk/source/NVDAHelper/typedCharacter.cpp- copied, changed from r2927,
/trunk/source/NVDAHelper/typedCharacter.c
trunk/source/appModules/logonui.py trunk/source/nvda_service.py trunk/source/nvda_slave.pyw trunk/source/shellapi.py Removed: trunk/source/NVDAHelper/IA2Support.c trunk/source/NVDAHelper/hookManager.c trunk/source/NVDAHelper/inputLangChange.c trunk/source/NVDAHelper/typedCharacter.c Modified: trunk/dependencies.txt trunk/installer/nvda.nsi trunk/source/IAccessibleHandler.py trunk/source/NVDAHelper/hookManager.h trunk/source/config/__init__.py trunk/source/gui/settingsDialogs.py trunk/source/nvda.pyw trunk/source/setup.py trunk/source/winKernel.py trunk/source/winUser.py trunk/user_docs/en/whats new.txt
Modified: trunk/dependencies.txt =================================================================
=============
NVDA miscellaneous dependencies package, version 2009-04-16-01 or later:--- trunk/dependencies.txt (original) +++ trunk/dependencies.txt Fri May 15 07:13:17 2009 @@ -7,7 +7,7 @@ http://www.wxpython.org/ Python Windows Extensions (for Python 2.6), build 212 or later: http://www.sourceforge.net/projects/pywin32/-Several other packages, made available for convenience in the
+Several other packages, made available for convenience in theNVDA miscellaneous dependencies package, version 2009-05-15-01 or later:
http://www.nvda-project.org/wiki/MiscellaneousDependencies
To build a binary version of NVDA, you will also need:
Modified: trunk/installer/nvda.nsi =================================================================
=============
--- trunk/installer/nvda.nsi (original) +++ trunk/installer/nvda.nsi Fri May 15 07:13:17 2009 @@ -11,6 +11,7 @@ !include "Library.nsh" !include "FileFunc.nsh"
+ ;-------- ;Settings
@@ -36,6 +37,7 @@ SetDateSave on XPStyle on InstProgressFlags Smooth +RequestExecutionLevel user /* RequestExecutionLevel REQUIRED! */ !define MUI_ABORTWARNING ;Should ask to exit !define MUI_UNINSTALLER ;We want an uninstaller to be generated
@@ -54,6 +56,8 @@ !define MUI_CUSTOMFUNCTION_GUIINIT NVDA_GUIInit !define MUI_CUSTOMFUNCTION_ABORT userAbort
+!include "serviceLib.nsh" + ;-------------------------------- ;Pages
@@ -71,6 +75,9 @@ ;Directory selection page !insertmacro MUI_PAGE_DIRECTORY
+;Components selection page +!insertmacro MUI_PAGE_COMPONENTS + ;Start menu page Var StartMenuFolder !define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKLM" @@ -153,6 +160,8 @@ ReserveFile "${NSISDIR}\Plugins\system.dll" ReserveFile "${NSISDIR}\Plugins\banner.dll" ReserveFile "waves\${SNDLogo}" +ReserveFile "UAC.dll" +!addplugindir "."
;----- ;Include install logger code (depends on some above settings) @@ -170,8 +179,7 @@ ;----- ;Sections
-;The only installable section -Section "install" +Section "-NVDA" SetShellVarContext all SetOutPath "$INSTDIR"; open and close uninstallation log after ennumerating all the
files being copied
@@ -214,10 +222,19 @@WriteRegStr ${INSTDIR_REG_ROOT} "Software\${PRODUCT}" ""
$INSTDIR
SectionEnd
"path=$INSTDIR\nvda_service.exe;autostart=1;display=NonVisual Desktop Access;description=Runs NVDA at Windows logon and in Windows security dialogs;"+section "nvda service (Windows logon / Security dialog support)"+!insertmacro SERVICE create "nvda"
+!insertmacro SERVICE "start" "nvda" "" +SectionEnd + ;The uninstall section Section "Uninstall" SetShellVarContext all - +;Stop and uninstall the service +!undef UN +!define UN "un." +!insertmacro SERVICE stop "nvda" "" +!insertmacro SERVICE delete "nvda" "" ; Uninstall libraries!insertmacro UninstallLib DLL NOTSHARED REBOOT_NOTPROTECTED
"$INSTDIR\lib\NVDAHelper.dll"
!insertmacro UninstallLib DLL NOTSHARED REBOOT_NOTPROTECTED
"$INSTDIR\lib\VBufBase.dll"
@@ -246,6 +263,18 @@ ;Functions
Function .onInit +UAC::RunElevated +;If couldn't change user then fail +strcmp 0 $0 +1 elevationFail +;If we are the outer user process, then silently quit +strcmp 1 $1 +1 +2 +quit +;If we are now an admin, success +strcmp 1 $3 elevationSuccess +elevationFail: +MessageBox mb_iconstop "Unable to elevate, error $0" +quit +elevationSuccess: strcpy $runAppOnInstSuccess "0"; Fix an error from previous installers where the "nvda" file
would be left behind after uninstall
IfFileExists "$PROGRAMFILES\NVDA" 0 @@ -356,7 +385,7 @@ !insertmacro UNINSTALL.LOG_UPDATE_INSTALL Execwait "$PLUGINSDIR\${NVDATempDir}\${NVDAApp} -q" strcmp $runAppOnInstSuccess "1" +1 end -Exec "$INSTDIR\${NVDAApp}" +uac::exec "" "$INSTDIR\${NVDAApp}" "" "" end: FunctionEnd
@@ -367,6 +396,7 @@ Function .onGUIEnd ; Clean up the temporary folder rmdir /R /REBOOTOK "$PLUGINSDIR\${NVDATempDir}" +UAC::Unload ;Must call unload! FunctionEnd
function makeRunAppOnInstSuccess
Modified: trunk/source/IAccessibleHandler.py =================================================================
=============
--- trunk/source/IAccessibleHandler.py (original) +++ trunk/source/IAccessibleHandler.py Fri May 15 07:13:17 2009 @@ -898,9 +898,6 @@ def _get_role(self): return controlTypes.ROLE_PANE
- def _get_description(self): - return _("Inaccessible to NVDA") - def processDesktopSwitchWinEvent(window,objectID,childID): hDesk=ctypes.windll.user32.OpenInputDesktop(0, False, 0) #name = ctypes.create_string_buffer(256)
Modified: trunk/source/NVDAHelper/hookManager.h =================================================================
=============
--- trunk/source/NVDAHelper/hookManager.h (original)+++ trunk/source/NVDAHelper/hookManager.h Fri May 15 07:13:17
2009
@@ -7,7 +7,7 @@ #include<windows.h #include<wchar.h
-#define DLLEXPORT __declspec(dllexport) +#define DLLEXPORT extern "C" __declspec(dllexport)
//Private variables extern HINSTANCE moduleHandle;
Added: trunk/source/appModules/logonui.py =================================================================
=============
--- (empty file) +++ trunk/source/appModules/logonui.py Fri May 15 07:13:17 2009 @@ -0,0 +1,44 @@ +import keyUtils +from NVDAObjects.IAccessible import IAccessible +import _default + +class PasswordField(IAccessible): + + def bindKeys(self): + for key, script in ( + ("extendedUp", "changeUser"), + ("extendedDown", "changeUser"), + ): + self.bindKey_runtime(key, script) + + def _get_name(self):+ # Focus automatically jumps to the password field when
a user is selected. This field has no name.
+ # This means that the new selected user is not
reported.
+ # Therefore, override the name of the password field to
be the selected user name.
+ try:+ # The accessibility hierarchy is totally screwed
here, so NVDA gets confused.
+ # Therefore, we'll have to do it the ugly way... + return self.IAccessibleObject.accParent.accName(0) + except: + return super(PasswordField, self).name + + def script_changeUser(self, key):+ # The up and down arrow keys change the selected user,
but there's no reliable NVDA event for detecting this.
+ oldName = self.name + keyUtils.sendKey(key) + if oldName == self.name: + return + self.event_gainFocus() + +class AppModule(_default.AppModule): + + def event_NVDAObject_init(self, obj):+ if obj.windowClassName == "NativeHWNDHost" and
obj.parent and not obj.parent.parent:
+ # Make sure the top level pane is always
presented.
+ obj.isPresentableFocusAncestor = True + return ++ if obj.windowClassName == "Edit" and not obj.name and
not obj.parent:
+ self.overlayCustomNVDAObjectClass(obj,
PasswordField, outerMost=True)
+ obj.bindKeys() + return
Modified: trunk/source/config/__init__.py =================================================================
=============
--- trunk/source/config/__init__.py (original) +++ trunk/source/config/__init__.py Fri May 15 07:13:17 2009 @@ -4,6 +4,7 @@ import globalVars import _winreg import os +import sys from cStringIO import StringIO from configobj import ConfigObj from validate import Validator @@ -205,3 +206,73 @@if
ctypes.windll.shell32.SHGetSpecialFolderPathW(0,buf,CSI DL_APPDATA,0):
return u'%s\\nvda'%buf.value return u'.\\' + +RUN_REGKEY = ur"SOFTWARE\Microsoft\Windows\CurrentVersion\Run" + +def getStartAfterLogon(): + try:+ k = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER,
RUN_REGKEY)
+ val = _winreg.QueryValueEx(k, u"nvda")[0] + return os.stat(val) == os.stat(sys.argv[0]) + except (WindowsError, OSError): + return False + +def setStartAfterLogon(enable):+ k = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, RUN_REGKEY,
0, _winreg.KEY_WRITE)
+ if enable:+ _winreg.SetValueEx(k, u"nvda", None, _winreg.REG_SZ,
sys.argv[0])
+ else: + _winreg.DeleteValue(k, u"nvda") + +SERVICE_FILENAME = u"nvda_service.exe" + +def isServiceInstalled(): + if not os.path.isfile(SERVICE_FILENAME): + return False + try:+ k = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,
ur"SYSTEM\CurrentControlSet\Services\nvda")
+ val = _winreg.QueryValueEx(k,
u"ImagePath")[0].replace(u'"', u'')
lpFile=os.path.abspath(path), lpParameters=params, nShow=winUser.SW_HIDE)+ return os.stat(val) == os.stat(SERVICE_FILENAME) + except (WindowsError, OSError): + return False + +def execElevated(path, params=None, wait=False): + import shellapi + import winKernel + import winUser+ sei = shellapi.SHELLEXECUTEINFO(lpVerb=u"runas",
+ if wait: + sei.fMask = shellapi.SEE_MASK_NOCLOSEPROCESS + shellapi.ShellExecuteEx(sei) + if wait: + try:+ winKernel.waitForSingleObject(sei.hProcess,
winKernel.INFINITE)
+ return winKernel.GetExitCodeProcess(sei.hProcess) + finally: + winKernel.closeHandle(sei.hProcess) + +SLAVE_FILENAME = u"nvda_slave.exe" + +NVDA_REGKEY = ur"SOFTWARE\NVDA" + +def getStartOnLogonScreen(): + try:+ k = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,
NVDA_REGKEY)
+ return bool(_winreg.QueryValueEx(k,
u"startOnLogonScreen")[0])
+ except WindowsError: + return False + +def _setStartOnLogonScreen(enable):+ k = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, NVDA_REGKEY,
0, _winreg.KEY_WRITE)
+ _winreg.SetValueEx(k, u"startOnLogonScreen", None,
_winreg.REG_DWORD, int(enable))
+ +def setStartOnLogonScreen(enable): + if getStartOnLogonScreen() == enable: + return + try: + # Try setting it directly. + _setStartOnLogonScreen(enable) + except WindowsError:+ # We probably don't have admin privs, so we need to
elevate to do this using the slave.
+ if execElevated(SLAVE_FILENAME,"config_setStartOnLogonScreen %d" % enable, wait=True) != 0:
+ raise RuntimeError("Slave failed to set
startOnLogonScreen")
Modified: trunk/source/gui/settingsDialogs.py =================================================================
=============
--- trunk/source/gui/settingsDialogs.py (original) +++ trunk/source/gui/settingsDialogs.py Fri May 15 07:13:17 2009 @@ -128,6 +128,16 @@log.debugWarning("Could not set log level list to
current log level")
logLevelSizer.Add(self.logLevelList)
settingsSizer.Add(logLevelSizer,border=10,flag=wx.BOTTO M)
+ self.startAfterLogonCheckBox = wx.CheckBox(self,wx.ID_ANY, label=_("&Automatically start NVDA after I log on to Windows"))
+
self.startAfterLogonCheckBox.SetValue(config.getStartAf terLogon())
wx.ID_ANY, label=_("Use NVDA on the Windows logon screen (requires administrator privileges)"))+ if not config.isInstalledCopy(): + self.startAfterLogonCheckBox.Disable() + settingsSizer.Add(self.startAfterLogonCheckBox)+ self.startOnLogonScreenCheckBox = wx.CheckBox(self,
+
self.startOnLogonScreenCheckBox.SetValue(config.getStar tOnLogonScreen())
+ if not config.isServiceInstalled(): + self.startOnLogonScreenCheckBox.Disable() + settingsSizer.Add(self.startOnLogonScreenCheckBox)
def postInit(self): self.languageList.SetFocus() @@ -147,6 +157,13 @@
logLevel=self.LOG_LEVELS[self.logLevelList.GetSelection ()][0]
config.conf["general"]["loggingLevel"]=logHandler.level Names[logLevel]
logHandler.setLogLevelFromConfig() + if self.startAfterLogonCheckBox.IsEnabled(): +
config.setStartAfterLogon(self.startAfterLogonChec kBox.GetValue())
+ if self.startOnLogonScreenCheckBox.IsEnabled(): + try: +
config.setStartOnLogonScreen(self.startOnLogo nScreenCheckBox.GetValue())
administrator privileges."), _("Insufficient Privileges"), style=wx.OK | wx.ICON_ERROR)+ except (WindowsError, RuntimeError):+ wx.MessageBox(_("This change requires
to take effect, the configuration must be saved and NVDA must be restarted. Press enter to save and restart NVDA, or cancel to manually save and exit at a later time."),_("Language Configuration Change"),wx.OK|wx.CANCEL|wx.ICON_WARNING).ShowModaif self.oldLanguage!=newLanguage:if wx.MessageDialog(self,_("For the new language
l()==wx.ID_OK:
config.save()
Modified: trunk/source/nvda.pyw =================================================================
=============
--- trunk/source/nvda.pyw (original) +++ trunk/source/nvda.pyw Fri May 15 07:13:17 2009 @@ -62,6 +62,7 @@ parser=NoConsoleOptionParser()
parser.add_option('-q','--quit',action="store_true",dest='quit',d efault=False,help="Quit already running copy of NVDA")
parser.add_option('-r','--replace',action="store_true",dest='replace',default=False,help="Quit already running copy of NVDA and start this one")
t='check_running',default=False,help="Report whether NVDA is running via the exit code; 0 if running, 1 if not running")+parser.add_option('-k','--check-running',action="store_true",des
parser.add_option('-f','--log-file',dest='logFileName',default=logFileName,help="The file where log messages should be written to")
parser.add_option('-l','--log-level',type="int",dest='logLevel',default=0,help="The lowest level of message logged (debug 10, info 20, warning 30, error 40, critical 50), default is warning")
parser.add_option('-c','--config-path',dest='configPath',default=config.getUserDefaultConfigPath(),help="The path where all settings for NVDA are stored")
@@ -87,6 +88,9 @@ sys.exit(1)if globalVars.appArgs.quit or (oldAppWindowHandle and not
globalVars.appArgs.replace):
sys.exit(0) +elif globalVars.appArgs.check_running: + # NVDA is not running. + sys.exit(1)
#os.environ['PYCHECKER']="--limit 10000 -q --changetypes" #import pychecker.checker
Added: trunk/source/nvda_service.py =================================================================
=============
--- (empty file) +++ trunk/source/nvda_service.py Fri May 15 07:13:17 2009 @@ -0,0 +1,288 @@ +from ctypes import * +from ctypes.wintypes import * +import threading +import win32serviceutil +import win32service +import sys +import os +import time +import _winreg + +CREATE_UNICODE_ENVIRONMENT=1024 +INFINITE = 0xffffffff +UOI_NAME = 2 +SYNCHRONIZE = 0x100000 +WAIT_OBJECT_0 = 0 +MAXIMUM_ALLOWED = 0x2000000 +SecurityIdentification = 2 +TokenPrimary = 1 +PROCESS_QUERY_INFORMATION = 0x0400 +TokenSessionId = 12 +TokenUIAccess = 26 +WTS_CONSOLE_CONNECT = 0x1 +WTS_CONSOLE_DISCONNECT = 0x2 +WTS_SESSION_LOGON = 0x5 +WTS_SESSION_LOGOFF = 0x6 +WTS_SESSION_LOCK = 0x7 +WTS_SESSION_UNLOCK = 0x8 +WTS_CURRENT_SERVER_HANDLE = 0 +WTSUserName = 5 + +nvdaExec = os.path.join(sys.prefix,"nvda.exe") +slaveExec = os.path.join(sys.prefix,"nvda_slave.exe") + +def debug(msg): + try:+ file(os.path.join(os.getenv("windir"), "temp",
"nvda_service.log"), "a").write(msg + "\n")
+ except (OSError, IOError): + pass + +def getInputDesktopName(): + desktop = windll.user32.OpenInputDesktop(0, False, 0) + name = create_unicode_buffer(256)+ windll.user32.GetUserObjectInformationW(desktop, UOI_NAME,
byref(name), sizeof(name), None)
+ windll.user32.CloseDesktop(desktop) + return ur"WinSta0\%s" % name.value + +class STARTUPINFO(Structure): + _fields_=[ + ('cb',DWORD), + ('lpReserved',LPWSTR), + ('lpDesktop',LPWSTR), + ('lpTitle',LPWSTR), + ('dwX',DWORD), + ('dwY',DWORD), + ('dwXSize',DWORD), + ('dwYSize',DWORD), + ('dwXCountChars',DWORD), + ('dwYCountChars',DWORD), + ('dwFillAttribute',DWORD), + ('dwFlags',DWORD), + ('wShowWindow',WORD), + ('cbReserved2',WORD), + ('lpReserved2',POINTER(c_byte)), + ('hSTDInput',HANDLE), + ('hSTDOutput',HANDLE), + ('hSTDError',HANDLE), + ] + +class PROCESS_INFORMATION(Structure): + _fields_=[ + ('hProcess',HANDLE), + ('hThread',HANDLE), + ('dwProcessID',DWORD), + ('dwThreadID',DWORD), + ] + +def getLoggedOnUserToken(session): + # Only works in Windows XP and above. + token = HANDLE() + windll.wtsapi32.WTSQueryUserToken(session, byref(token)) + return token.value + +def duplicateTokenPrimary(token): + newToken = HANDLE()+ windll.advapi32.DuplicateTokenEx(token, MAXIMUM_ALLOWED,
None, SecurityIdentification, TokenPrimary, byref(newToken))
windll.kernel32.OpenProcess(PROCESS_QUERY_INFORMATION, False, os.getpid())+ windll.kernel32.CloseHandle(token) + return newToken.value + +def getOwnToken():+ process =
+ token = HANDLE()+ windll.advapi32.OpenProcessToken(process, MAXIMUM_ALLOWED,
byref(token))
+ windll.kernel32.CloseHandle(process) + return token + +def getSessionSystemToken(session): + token = duplicateTokenPrimary(getOwnToken()) + session = DWORD(session)+ windll.advapi32.SetTokenInformation(token, TokenSessionId,
byref(session), sizeof(DWORD))
+ return token + +def executeProcess(desktop, token, executable, *argStrings): + argsString=" ".join(list(argStrings)) +
startupInfo=STARTUPINFO(cb=sizeof(STARTUPINFO),lpDesktop=des ktop)
+ processInformation=PROCESS_INFORMATION()+ cmdBuf=create_unicode_buffer(u'"%s"
%s'%(executable,argsString))
+ if token: + env=c_void_p() +
windll.userenv.CreateEnvironmentBlock(byref(env),token, False)
None, cmdBuf,None,None,False,CREATE_UNICODE_ENVIRONMENT,+ try:+ if windll.advapi32.CreateProcessAsUserW(token,
env,None,byref(startupInfo),byref(processInformati on)) == 0:
+ raise WinError() + finally: + windll.kernel32.CloseHandle(token) + windll.userenv.DestroyEnvironmentBlock(env) + else:+ if windll.kernel32.CreateProcessW(None,
cmdBuf,None,None,False,0,None,None,byref(startupInfo),b yref(processInformation)) == 0:
+ raise WinError() + return processInformation.hProcess + +def nvdaLauncher(): + desktop = getInputDesktopName() + if desktop == ur"WinSta0\Default": + return + + startNVDA(desktop)+ desktopSwitchEvt = windll.kernel32.OpenEventW(SYNCHRONIZE,
False, u"WinSta0_DesktopSwitch")
+ windll.kernel32.WaitForSingleObject(desktopSwitchEvt,
INFINITE)
+ windll.kernel32.CloseHandle(desktopSwitchEvt) + exitNVDA(desktop) + +def startNVDA(desktop): + process = executeProcess(desktop, None, nvdaExec, "-m") + windll.kernel32.CloseHandle(process) + +def startNVDAUIAccess(session, desktop): + token = duplicateTokenPrimary(getLoggedOnUserToken(session)) + uiAccess = ULONG(1)+ windll.advapi32.SetTokenInformation(token, TokenUIAccess,
byref(uiAccess), sizeof(ULONG))
+ process = executeProcess(desktop, token, nvdaExec, "-m") + windll.kernel32.CloseHandle(process) + +def exitNVDA(desktop): + process = executeProcess(desktop, None, nvdaExec, "-q") + windll.kernel32.WaitForSingleObject(process, 10000) + windll.kernel32.CloseHandle(process) + +def isUserRunningNVDA(session): + token = getSessionSystemToken(session)+ process = executeProcess(ur"WinSta0\Default", token,
nvdaExec, u"--check-running")
+ windll.kernel32.WaitForSingleObject(process, INFINITE) + exitCode = DWORD() + windll.kernel32.GetExitCodeProcess(process, byref(exitCode)) + windll.kernel32.CloseHandle(process) + return exitCode.value == 0 + +def isSessionLoggedOn(session): + username = c_wchar_p() + size = DWORD() +
windll.wtsapi32.WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, session, WTSUserName, byref(username), byref(size))
+ ret = bool(username.value) + windll.wtsapi32.WTSFreeMemory(username) + return ret + +def execBg(func): + t = threading.Thread(target=func) + t.setDaemon(True) + t.start() + +def shouldStartOnLogonScreen(): + try:+ k = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,
ur"SOFTWARE\NVDA")
+ return bool(_winreg.QueryValueEx(k,
u"startOnLogonScreen")[0])
+ except WindowsError: + return False + +class NVDAService(win32serviceutil.ServiceFramework): + + _svc_name_="nvda" + _svc_display_name_="nonVisual Desktop Access" + + def GetAcceptedControls(self):+ return
win32serviceutil.ServiceFramework.GetAcceptedControls(s elf) | win32service.SERVICE_ACCEPT_SESSIONCHANGE
+ + def initSession(self, session): + debug("init session %d" % session) + self.session = session + self.launcherLock = threading.RLock() + self.launcherStarted = False + self.desktopSwitchSupervisorStarted = False + self.isSessionLoggedOn = isSessionLoggedOn(session) + debug("session logged on: %r" % self.isSessionLoggedOn) + + if self.isSessionLoggedOn:+ # The session is logged on, so treat this as a
normal desktop switch.
+ self.handleDesktopSwitch() + execBg(self.desktopSwitchSupervisor) + else: + # We're at the logon screen. + if shouldStartOnLogonScreen(): + execBg(self.startLauncher)+ # The desktop switch supervisor will be started by
the logon event.
+ + def desktopSwitchSupervisor(self): + if self.desktopSwitchSupervisorStarted: + return + self.desktopSwitchSupervisorStarted = True + origSession = self.session+ debug("starting desktop switch supervisor, session %d"
% origSession)
+ desktopSwitchEvt =windll.kernel32.OpenEventW(SYNCHRONIZE, False, u"Session\%d\WinSta0_DesktopSwitch" % self.session)
+ if not desktopSwitchEvt: + try: + raise WinError() + except Exception, e: + debug("error opening event: %s" % e) + raise + + while self.session == origSession: +
windll.kernel32.WaitForSingleObject(desktopSwitchE vt, INFINITE)
+ debug("desktop switch, session %r" % self.session) + self.handleDesktopSwitch() + + windll.kernel32.CloseHandle(desktopSwitchEvt)+ debug("desktop switch supervisor terminated, session
%d" % origSession)
shouldStartOnLogonScreen()) or isUserRunningNVDA(self.session):+ + def handleDesktopSwitch(self): + with self.launcherLock: + self.launcherStarted = False ++ if (not self.isSessionLoggedOn and
+ self.startLauncher() + else: + debug("not starting launcher") + + def SvcOtherEx(self, control, eventType, data):+ if control ==
win32service.SERVICE_CONTROL_SESSIONCHANGE:
+ self.handleSessionChange(eventType, data[0]) + + def handleSessionChange(self, event, session): + if event == WTS_CONSOLE_CONNECT: + debug("connect %d" % session) + if session != self.session: + self.initSession(session) + elif event == WTS_SESSION_LOGON: + debug("logon %d" % session) + self.isSessionLoggedOn = True + execBg(self.desktopSwitchSupervisor) + elif event == WTS_SESSION_LOGOFF: + debug("logoff %d" % session) + self.isSessionLoggedOn = False + # We may be heading back to the logon screen. + if shouldStartOnLogonScreen(): + execBg(self.startLauncher) + elif event == WTS_SESSION_LOCK: + debug("lock %d" % session) + if session == self.session:+ # We always start NVDA for the lock/switch
user screen.
executeProcess(ur"WinSta0\Winlogon", token, slaveExec, u"service_NVDALauncher")+ self.startLauncher() + + def startLauncher(self): + with self.launcherLock: + if self.launcherStarted: + return + + debug("attempt launcher start") + token = getSessionSystemToken(self.session) + try:+ process =
+ self.launcherStarted = True + debug("launcher started") + windll.kernel32.CloseHandle(process) + except Exception, e: + debug("error starting launcher: %s" % e) + + def SvcDoRun(self): + debug("service starting") + self.exitEvent = threading.Event() +
self.initSession(windll.kernel32.WTSGetActiveConsoleSes sionId())
+ self.exitEvent.wait() + debug("service exiting") + + def SvcStop(self): + self.exitEvent.set() + +if __name__=='__main__': + if not getattr(sys, "frozen", None):+ raise RuntimeError("Can only be run compiled with
py2exe")
+ win32serviceutil.HandleCommandLine(NVDAService)
Added: trunk/source/nvda_slave.pyw =================================================================
=============
--- (empty file) +++ trunk/source/nvda_slave.pyw Fri May 15 07:13:17 2009 @@ -0,0 +1,32 @@ +"""NVDA slave process+Performs miscellaneous tasks which need to be performed in a
separate process.
+""" + +import sys +if hasattr(sys, "frozen"):+ # Error messages (which are only for debugging) should not
cause the py2exe log message box to appear.
+ sys.stderr = sys.stdout + +def main(): + try: + action = sys.argv[1] + except IndexError: + sys.exit("No action") + args = sys.argv[2:] + + try: + if action == "service_NVDALauncher": + import nvda_service + nvda_service.nvdaLauncher() + elif action == "config_setStartOnLogonScreen": + enable = bool(int(args[0])) + import config + config._setStartOnLogonScreen(enable) + else: + raise ValueError("No such action") + + except Exception, e: + sys.exit(e) + +if __name__ == "__main__": + main()
Modified: trunk/source/setup.py =================================================================
=============
--- trunk/source/setup.py (original) +++ trunk/source/setup.py Fri May 15 07:13:17 2009 @@ -98,13 +98,31 @@ 'Operating System :: Microsoft :: Windows', ], cmdclass={"py2exe": py2exe}, - windows = [{ - "script":"nvda.pyw", - "uac_info": ("asInvoker", False), - "icon_resources":[(1,"images/nvda.ico")], - "version":"0.0.0.0", - "product_version":version, - "copyright":copyright, + windows=[ + { + "script":"nvda.pyw", + "uac_info": ("asInvoker", False), + "icon_resources":[(1,"images/nvda.ico")], + "version":"0.0.0.0", + "product_version":version, + "copyright":copyright, + }, + { + "script": "nvda_slave.pyw", + "icon_resources": [(1,"images/nvda.ico")], + "version": "0.0.0.0", + "product_version": version, + "copyright": copyright, + }, + ], + service=[{ + "modules": ["nvda_service"], + "icon_resources": [(1, "images/nvda.ico")], + "version": "0.0.0.0", + "product_version": version, + "copyright": copyright, + "uac_info": ("requireAdministrator", False), + "cmdline_style": "pywin32", }], options = {"py2exe": { "bundle_files": 3, @@ -112,7 +130,6 @@ "packages": ["NVDAObjects","virtualBuffers"], "includes": getOptionalIncludes(), }}, - zipfile = None, data_files=[ (".",glob("*.dll")+glob("*.manifest")+["builtin.dic"]),("documentation", ['../copying.txt',
'../contributors.txt']),
Added: trunk/source/shellapi.py =================================================================
=============
--- (empty file) +++ trunk/source/shellapi.py Fri May 15 07:13:17 2009 @@ -0,0 +1,38 @@ +#shellapi.py +#A part of NonVisual Desktop Access (NVDA)+#Copyright (C) 2006-2009 NVDA
Contributors<http://www.nvda-project.org/
+#This file is covered by the GNU General Public License. +#See the file COPYING for more details. + +from ctypes import * +from ctypes.wintypes import * + +shell32 = windll.shell32 + +class SHELLEXECUTEINFOW(Structure): + _fields_ = ( + ("cbSize", DWORD), + ("fMask", ULONG), + ("hwnd", HWND), + ("lpVerb", LPCWSTR), + ("lpFile", LPCWSTR), + ("lpParameters", LPCWSTR), + ("lpDirectory", LPCWSTR), + ("nShow", c_int), + ("hInstApp", HINSTANCE), + ("lpIDList", LPVOID), + ("lpClass", LPCWSTR), + ("hkeyClass", HKEY), + ("dwHotKey", DWORD), + ("hIconOrMonitor", HANDLE), + ("hProcess", HANDLE), + ) + def __init__(self, **kwargs):+ super(SHELLEXECUTEINFOW,
self).__init__(cbSize=sizeof(self), **kwargs)
+SHELLEXECUTEINFO = SHELLEXECUTEINFOW + +SEE_MASK_NOCLOSEPROCESS = 0x00000040 + +def ShellExecuteEx(execInfo): + if not shell32.ShellExecuteExW(byref(execInfo)): + raise WinError()
Modified: trunk/source/winKernel.py =================================================================
=============
--- trunk/source/winKernel.py (original) +++ trunk/source/winKernel.py Fri May 15 07:13:17 2009 @@ -101,3 +101,9 @@ res = kernel32.SetProcessShutdownParameters(level, flags) if res == 0: raise ctypes.WinError() + +def GetExitCodeProcess(process): + exitCode = ctypes.wintypes.DWORD()+ if not kernel32.GetExitCodeProcess(process,
ctypes.byref(exitCode)):
+ raise ctypes.WinError() + return exitCode.value
Modified: trunk/source/winUser.py =================================================================
=============
--- trunk/source/winUser.py (original) +++ trunk/source/winUser.py Fri May 15 07:13:17 2009 @@ -237,6 +237,10 @@ EVENT_CONSOLE_START_APPLICATION=0x4006 EVENT_CONSOLE_END_APPLICATION=0x4007
+# ShowWindow() commands +SW_HIDE = 0 +SW_SHOWNORMAL = 1 + def setSystemScreenReaderFlag(val):
user32.SystemParametersInfoW(SPI_SETSCREENREADER,val,0,SPIF_ SENDCHANGE)
Modified: trunk/user_docs/en/whats new.txt =================================================================
=============
(either because a UAC control dialog appeared, or because control+alt+delete was pressed), NVDA will announce the fact that the user is now on the secure desktop. This desktop is still not accessible to NVDA, though the user at least is notified as to what happened.--- trunk/user_docs/en/whats new.txt (original) +++ trunk/user_docs/en/whats new.txt Fri May 15 07:13:17 2009 @@ -24,8 +24,11 @@*New: In Windows Vista, if the user moves to the secure desktop
*Fix: better support for Dos consoles. specifically: NVDA cannow read the content of particular consoles it always used to think were blank. Pressing control+break no longer terminates NVDA.
*New: NVDA can announce text under the mouse within dos
console windows.
+* new: NVDA can be configured to start automatically after you
log on to Windows. The option is in the General Settings dialog.
+* new: NVDA can read secure Windows screens such as the Windowslogon, control+alt+delete and UAC screens in Windows XP and above. Reading of the Windows logon screen can be configured from the General Settings dialog. (#97)
+* fix: On Windows Vista, the NVDA installer now starts NVDA withnormal user privileges when requested to run NVDA on the finish screen.
NVDA, provide an NVDA specific dialog box for editing when the user presses f2 on a cell.- Changes since 0.6 P2: +Changes since 0.6 P2:* new: As Microsoft Excel's formula bar is inaccessible to
* change: If the audio output device is set to use the Windowsdefault device (Microsoft Sound Mapper), NVDA will now switch to the new default device for eSpeak and tones when the default device changes. For example, NVDA will switch to a USB audio device if it automatically becomes the default device when it is connected.
* fix: The last chunk of audio is no longer cut off when using
NVDA with eSpeak on a remote desktop server.
_______________________________________________ Nvda-dev mailing list Nvda-dev@xxxxxxxxxxxxxxxxxx http://lists.nvaccess.org/listinfo/nvda-dev
blind_html To unsubscribe, please send a blank email to blind_html-request@xxxxxxxxxxxxx with unsubscribe in the subject line. To access the archives, please visit: //www.freelists.org/archive/blind_html
Thanks
blind_html To unsubscribe, please send a blank email to blind_html-request@xxxxxxxxxxxxx with unsubscribe in the subject line. To access the archives, please visit: //www.freelists.org/archive/blind_html Thanks