1 # -*- test-case-name: twisted.python.test.test_win32 -*-
2 # Copyright (c) Twisted Matrix Laboratories.
3 # See LICENSE for details.
8 See also twisted.python.shortcut.
10 @var O_BINARY: the 'binary' mode flag on Windows, or 0 on other platforms, so it
11 may safely be OR'ed into a mask for os.open.
24 from twisted.python.runtime import platform
26 # http://msdn.microsoft.com/library/default.asp?url=/library/en-us/debug/base/system_error_codes.asp
27 ERROR_FILE_NOT_FOUND = 2
28 ERROR_PATH_NOT_FOUND = 3
29 ERROR_INVALID_NAME = 123
32 O_BINARY = getattr(os, "O_BINARY", 0)
34 def _determineWindowsError():
36 Determine which WindowsError name to export.
38 return getattr(exceptions, 'WindowsError', FakeWindowsError)
40 class FakeWindowsError(OSError):
42 Stand-in for sometimes-builtin exception on platforms for which it
46 WindowsError = _determineWindowsError()
48 # XXX fix this to use python's builtin _winreg?
50 def getProgramsMenuPath():
51 """Get the path to the Programs menu.
53 Probably will break on non-US Windows.
55 @returns: the filesystem location of the common Start Menu->Programs.
57 if not platform.isWinNT():
58 return "C:\\Windows\\Start Menu\\Programs"
59 keyname = 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders'
60 hShellFolders = win32api.RegOpenKeyEx(win32con.HKEY_LOCAL_MACHINE,
61 keyname, 0, win32con.KEY_READ)
62 return win32api.RegQueryValueEx(hShellFolders, 'Common Programs')[0]
65 def getProgramFilesPath():
66 """Get the path to the Program Files folder."""
67 keyname = 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion'
68 currentV = win32api.RegOpenKeyEx(win32con.HKEY_LOCAL_MACHINE,
69 keyname, 0, win32con.KEY_READ)
70 return win32api.RegQueryValueEx(currentV, 'ProgramFilesDir')[0]
72 _cmdLineQuoteRe = re.compile(r'(\\*)"')
73 _cmdLineQuoteRe2 = re.compile(r'(\\+)\Z')
76 Internal method for quoting a single command-line argument.
78 @param s: an unquoted string that you want to quote so that something that
79 does cmd.exe-style unquoting will interpret it as a single argument,
80 even if it contains spaces.
83 @return: a quoted string.
86 quote = ((" " in s) or ("\t" in s) or ('"' in s) or s == '') and '"' or ''
87 return quote + _cmdLineQuoteRe2.sub(r"\1\1", _cmdLineQuoteRe.sub(r'\1\1\\"', s)) + quote
89 def quoteArguments(arguments):
91 Quote an iterable of command-line arguments for passing to CreateProcess or
92 a similar API. This allows the list passed to C{reactor.spawnProcess} to
93 match the child process's C{sys.argv} properly.
95 @param arglist: an iterable of C{str}, each unquoted.
97 @return: a single string, with the given sequence quoted as necessary.
99 return ' '.join([cmdLineQuote(a) for a in arguments])
102 class _ErrorFormatter(object):
104 Formatter for Windows error messages.
106 @ivar winError: A callable which takes one integer error number argument
107 and returns an L{exceptions.WindowsError} instance for that error (like
110 @ivar formatMessage: A callable which takes one integer error number
111 argument and returns a C{str} giving the message for that error (like
112 L{win32api.FormatMessage}).
114 @ivar errorTab: A mapping from integer error numbers to C{str} messages
115 which correspond to those erorrs (like L{socket.errorTab}).
117 def __init__(self, WinError, FormatMessage, errorTab):
118 self.winError = WinError
119 self.formatMessage = FormatMessage
120 self.errorTab = errorTab
122 def fromEnvironment(cls):
124 Get as many of the platform-specific error translation objects as
125 possible and return an instance of C{cls} created with them.
128 from ctypes import WinError
132 from win32api import FormatMessage
136 from socket import errorTab
139 return cls(WinError, FormatMessage, errorTab)
140 fromEnvironment = classmethod(fromEnvironment)
143 def formatError(self, errorcode):
145 Returns the string associated with a Windows error message, such as the
146 ones found in socket.error.
148 Attempts direct lookup against the win32 API via ctypes and then
149 pywin32 if available), then in the error table in the socket module,
150 then finally defaulting to C{os.strerror}.
152 @param errorcode: the Windows error code
153 @type errorcode: C{int}
155 @return: The error message string
158 if self.winError is not None:
159 return self.winError(errorcode).strerror
160 if self.formatMessage is not None:
161 return self.formatMessage(errorcode)
162 if self.errorTab is not None:
163 result = self.errorTab.get(errorcode)
164 if result is not None:
166 return os.strerror(errorcode)
168 formatError = _ErrorFormatter.fromEnvironment().formatError