Initial import to Tizen
[profile/ivi/python-twisted.git] / twisted / python / win32.py
1 # -*- test-case-name: twisted.python.test.test_win32 -*-
2 # Copyright (c) Twisted Matrix Laboratories.
3 # See LICENSE for details.
4
5 """
6 Win32 utilities.
7
8 See also twisted.python.shortcut.
9
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.
12 """
13
14 import re
15 import exceptions
16 import os
17
18 try:
19     import win32api
20     import win32con
21 except ImportError:
22     pass
23
24 from twisted.python.runtime import platform
25
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
30 ERROR_DIRECTORY = 267
31
32 O_BINARY = getattr(os, "O_BINARY", 0)
33
34 def _determineWindowsError():
35     """
36     Determine which WindowsError name to export.
37     """
38     return getattr(exceptions, 'WindowsError', FakeWindowsError)
39
40 class FakeWindowsError(OSError):
41     """
42     Stand-in for sometimes-builtin exception on platforms for which it
43     is missing.
44     """
45
46 WindowsError = _determineWindowsError()
47
48 # XXX fix this to use python's builtin _winreg?
49
50 def getProgramsMenuPath():
51     """Get the path to the Programs menu.
52
53     Probably will break on non-US Windows.
54
55     @returns: the filesystem location of the common Start Menu->Programs.
56     """
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]
63
64
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]
71
72 _cmdLineQuoteRe = re.compile(r'(\\*)"')
73 _cmdLineQuoteRe2 = re.compile(r'(\\+)\Z')
74 def cmdLineQuote(s):
75     """
76     Internal method for quoting a single command-line argument.
77
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.
81     @type s: C{str}
82
83     @return: a quoted string.
84     @rtype: C{str}
85     """
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
88
89 def quoteArguments(arguments):
90     """
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.
94
95     @param arglist: an iterable of C{str}, each unquoted.
96
97     @return: a single string, with the given sequence quoted as necessary.
98     """
99     return ' '.join([cmdLineQuote(a) for a in arguments])
100
101
102 class _ErrorFormatter(object):
103     """
104     Formatter for Windows error messages.
105
106     @ivar winError: A callable which takes one integer error number argument
107         and returns an L{exceptions.WindowsError} instance for that error (like
108         L{ctypes.WinError}).
109
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}).
113
114     @ivar errorTab: A mapping from integer error numbers to C{str} messages
115         which correspond to those erorrs (like L{socket.errorTab}).
116     """
117     def __init__(self, WinError, FormatMessage, errorTab):
118         self.winError = WinError
119         self.formatMessage = FormatMessage
120         self.errorTab = errorTab
121
122     def fromEnvironment(cls):
123         """
124         Get as many of the platform-specific error translation objects as
125         possible and return an instance of C{cls} created with them.
126         """
127         try:
128             from ctypes import WinError
129         except ImportError:
130             WinError = None
131         try:
132             from win32api import FormatMessage
133         except ImportError:
134             FormatMessage = None
135         try:
136             from socket import errorTab
137         except ImportError:
138             errorTab = None
139         return cls(WinError, FormatMessage, errorTab)
140     fromEnvironment = classmethod(fromEnvironment)
141
142
143     def formatError(self, errorcode):
144         """
145         Returns the string associated with a Windows error message, such as the
146         ones found in socket.error.
147
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}.
151
152         @param errorcode: the Windows error code
153         @type errorcode: C{int}
154
155         @return: The error message string
156         @rtype: C{str}
157         """
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:
165                 return result
166         return os.strerror(errorcode)
167
168 formatError = _ErrorFormatter.fromEnvironment().formatError