It is on the website. It's the developer's mailing list. Thanks Nimer J Paul Tandy wrote:
Hey, How did you subscribe to that list? Thanks: Paulinstaller 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/guiuser_docs/enDate: Fri, 15 May 2009 07:13:21 +0000 From: NVDA Subversion <svn@xxxxxxxxxxxxxxxxReply-To: News and discussion for NVDA (NonVisual DesktopAccess), afree and open source screen reader for Microsoft Windows <nvda-dev@xxxxxxxxxxxxxxxxxx To: nvda-dev@xxxxxxxxxxxxxxxxxxAuthor: nvda Date: Fri May 15 07:13:17 2009 New Revision: 2928Log:* new: NVDA can be configured to start automatically afteryou log on to Windows. The option is in the General Settings dialog.* 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.ctrunk/source/NVDAHelper/hookManager.cpp- copied, changed from r2927,/trunk/source/NVDAHelper/hookManager.ctrunk/source/NVDAHelper/inputLangChange.cpp- copied, changed from r2927,/trunk/source/NVDAHelper/inputLangChange.ctrunk/source/NVDAHelper/typedCharacter.cpp- copied, changed from r2927,/trunk/source/NVDAHelper/typedCharacter.ctrunk/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.txtModified: trunk/dependencies.txt ==============================================================================--- 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 theNVDA miscellaneous dependencies package, version 2009-04-16-01 or later:+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/MiscellaneousDependenciesTo 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 thefiles being copied@@ -214,10 +222,19 @@WriteRegStr ${INSTDIR_REG_ROOT} "Software\${PRODUCT}" ""$INSTDIRSectionEnd"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 @@ ;FunctionsFunction .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" filewould be left behind after uninstallIfFileExists "$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! FunctionEndfunction makeRunAppOnInstSuccessModified: 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:172009@@ -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 whena user is selected. This field has no name.+ # This means that the new selected user is notreported.+ # Therefore, override the name of the password field tobe the selected user name.+ try:+ # The accessibility hierarchy is totally screwedhere, 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" andobj.parent and not obj.parent.parent:+ # Make sure the top level pane is alwayspresented.+ obj.isPresentableFocusAncestor = True + return ++ if obj.windowClassName == "Edit" and not obj.name andnot obj.parent:+ self.overlayCustomNVDAObjectClass(obj,PasswordField, outerMost=True)+ obj.bindKeys() + returnModified: 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 @@ifctypes.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'')+ 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",lpFile=os.path.abspath(path), lpParameters=params, nShow=winUser.SW_HIDE)+ 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 toelevate to do this using the slave.+ if execElevated(SLAVE_FILENAME,"config_setStartOnLogonScreen %d" % enable, wait=True) != 0:+ raise RuntimeError("Slave failed to setstartOnLogonScreen")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 tocurrent 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 requiresto 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 languagel()==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",desparser.add_option('-f','--log-file',dest='logFileName',default=lo gFileName,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 notglobalVars.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.checkerAdded: 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)+ try:+ if windll.advapi32.CreateProcessAsUserW(token,None, cmdBuf,None,None,False,CREATE_UNICODE_ENVIRONMENT, 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_SERV ER_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):+ returnwin32serviceutil.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 anormal 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 bythe 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)+ + def handleDesktopSwitch(self): + with self.launcherLock: + self.launcherStarted = False ++ if (not self.isSessionLoggedOn andshouldStartOnLogonScreen()) or isUserRunningNVDA(self.session):+ 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/switchuser 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 withpy2exe")+ 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 aseparate process.+""" + +import sys +if hasattr(sys, "frozen"):+ # Error messages (which are only for debugging) should notcause 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 NVDAContributors<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.valueModified: 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 dosconsole windows.+* new: NVDA can be configured to start automatically after youlog 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 usingNVDA with eSpeak on a remote desktop server._______________________________________________ Nvda-dev mailing list Nvda-dev@xxxxxxxxxxxxxxxxxx http://lists.nvaccess.org/listinfo/nvda-devblind_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_htmlThanksblind_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