| OLD | NEW |
| (Empty) |
| 1 # Copyright (c) 2001-2007 Twisted Matrix Laboratories. | |
| 2 # See LICENSE for details. | |
| 3 | |
| 4 """ | |
| 5 Win32 utilities. | |
| 6 | |
| 7 See also twisted.python.shortcut. | |
| 8 """ | |
| 9 | |
| 10 import re | |
| 11 import exceptions | |
| 12 import os | |
| 13 | |
| 14 try: | |
| 15 import win32api | |
| 16 import win32con | |
| 17 except ImportError: | |
| 18 pass | |
| 19 | |
| 20 from twisted.python.runtime import platform | |
| 21 | |
| 22 # http://msdn.microsoft.com/library/default.asp?url=/library/en-us/debug/base/sy
stem_error_codes.asp | |
| 23 ERROR_FILE_NOT_FOUND = 2 | |
| 24 ERROR_PATH_NOT_FOUND = 3 | |
| 25 ERROR_INVALID_NAME = 123 | |
| 26 ERROR_DIRECTORY = 267 | |
| 27 | |
| 28 def _determineWindowsError(): | |
| 29 """ | |
| 30 Determine which WindowsError name to export. | |
| 31 """ | |
| 32 return getattr(exceptions, 'WindowsError', FakeWindowsError) | |
| 33 | |
| 34 class FakeWindowsError(OSError): | |
| 35 """ | |
| 36 Stand-in for sometimes-builtin exception on platforms for which it | |
| 37 is missing. | |
| 38 """ | |
| 39 | |
| 40 WindowsError = _determineWindowsError() | |
| 41 | |
| 42 # XXX fix this to use python's builtin _winreg? | |
| 43 | |
| 44 def getProgramsMenuPath(): | |
| 45 """Get the path to the Programs menu. | |
| 46 | |
| 47 Probably will break on non-US Windows. | |
| 48 | |
| 49 @returns: the filesystem location of the common Start Menu->Programs. | |
| 50 """ | |
| 51 if not platform.isWinNT(): | |
| 52 return "C:\\Windows\\Start Menu\\Programs" | |
| 53 keyname = 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Fol
ders' | |
| 54 hShellFolders = win32api.RegOpenKeyEx(win32con.HKEY_LOCAL_MACHINE, | |
| 55 keyname, 0, win32con.KEY_READ) | |
| 56 return win32api.RegQueryValueEx(hShellFolders, 'Common Programs')[0] | |
| 57 | |
| 58 | |
| 59 def getProgramFilesPath(): | |
| 60 """Get the path to the Program Files folder.""" | |
| 61 keyname = 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion' | |
| 62 currentV = win32api.RegOpenKeyEx(win32con.HKEY_LOCAL_MACHINE, | |
| 63 keyname, 0, win32con.KEY_READ) | |
| 64 return win32api.RegQueryValueEx(currentV, 'ProgramFilesDir')[0] | |
| 65 | |
| 66 _cmdLineQuoteRe = re.compile(r'(\\*)"') | |
| 67 _cmdLineQuoteRe2 = re.compile(r'(\\+)\Z') | |
| 68 def cmdLineQuote(s): | |
| 69 """ | |
| 70 Internal method for quoting a single command-line argument. | |
| 71 | |
| 72 @param s: an unquoted string that you want to quote so that something that | |
| 73 does cmd.exe-style unquoting will interpret it as a single argument, even | |
| 74 if it contains spaces. | |
| 75 | |
| 76 @return: a quoted string. | |
| 77 """ | |
| 78 quote = ((" " in s) or ("\t" in s) or ('"' in s)) and '"' or '' | |
| 79 return quote + _cmdLineQuoteRe2.sub(r"\1\1", _cmdLineQuoteRe.sub(r'\1\1\\"',
s)) + quote | |
| 80 | |
| 81 def quoteArguments(arguments): | |
| 82 """ | |
| 83 Quote an iterable of command-line arguments for passing to CreateProcess or | |
| 84 a similar API. This allows the list passed to C{reactor.spawnProcess} to | |
| 85 match the child process's C{sys.argv} properly. | |
| 86 | |
| 87 @param arglist: an iterable of C{str}, each unquoted. | |
| 88 | |
| 89 @return: a single string, with the given sequence quoted as necessary. | |
| 90 """ | |
| 91 return ' '.join([cmdLineQuote(a) for a in arguments]) | |
| 92 | |
| 93 | |
| 94 class _ErrorFormatter(object): | |
| 95 """ | |
| 96 Formatter for Windows error messages. | |
| 97 | |
| 98 @ivar winError: A callable which takes one integer error number argument | |
| 99 and returns an L{exceptions.WindowsError} instance for that error (like | |
| 100 L{ctypes.WinError}). | |
| 101 | |
| 102 @ivar formatMessage: A callable which takes one integer error number | |
| 103 argument and returns a C{str} giving the message for that error (like | |
| 104 L{win32api.FormatMessage}). | |
| 105 | |
| 106 @ivar errorTab: A mapping from integer error numbers to C{str} messages | |
| 107 which correspond to those erorrs (like L{socket.errorTab}). | |
| 108 """ | |
| 109 def __init__(self, WinError, FormatMessage, errorTab): | |
| 110 self.winError = WinError | |
| 111 self.formatMessage = FormatMessage | |
| 112 self.errorTab = errorTab | |
| 113 | |
| 114 def fromEnvironment(cls): | |
| 115 """ | |
| 116 Get as many of the platform-specific error translation objects as | |
| 117 possible and return an instance of C{cls} created with them. | |
| 118 """ | |
| 119 try: | |
| 120 from ctypes import WinError | |
| 121 except ImportError: | |
| 122 WinError = None | |
| 123 try: | |
| 124 from win32api import FormatMessage | |
| 125 except ImportError: | |
| 126 FormatMessage = None | |
| 127 try: | |
| 128 from socket import errorTab | |
| 129 except ImportError: | |
| 130 errorTab = None | |
| 131 return cls(WinError, FormatMessage, errorTab) | |
| 132 fromEnvironment = classmethod(fromEnvironment) | |
| 133 | |
| 134 | |
| 135 def formatError(self, errorcode): | |
| 136 """ | |
| 137 Returns the string associated with a Windows error message, such as the | |
| 138 ones found in socket.error. | |
| 139 | |
| 140 Attempts direct lookup against the win32 API via ctypes and then | |
| 141 pywin32 if available), then in the error table in the socket module, | |
| 142 then finally defaulting to C{os.strerror}. | |
| 143 | |
| 144 @param errorcode: the Windows error code | |
| 145 @type errorcode: C{int} | |
| 146 | |
| 147 @return: The error message string | |
| 148 @rtype: C{str} | |
| 149 """ | |
| 150 if self.winError is not None: | |
| 151 return self.winError(errorcode)[1] | |
| 152 if self.formatMessage is not None: | |
| 153 return self.formatMessage(errorcode) | |
| 154 if self.errorTab is not None: | |
| 155 result = self.errorTab.get(errorcode) | |
| 156 if result is not None: | |
| 157 return result | |
| 158 return os.strerror(errorcode) | |
| 159 | |
| 160 formatError = _ErrorFormatter.fromEnvironment().formatError | |
| OLD | NEW |