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 |