##// END OF EJS Templates
win32: allow catching of both pywintypes.error and WindowsError
Bryan O'Sullivan -
r8328:91f1fe78 default
parent child Browse files
Show More
@@ -1,380 +1,386
1 # win32.py - utility functions that use win32 API
1 # win32.py - utility functions that use win32 API
2 #
2 #
3 # Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
3 # Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2, incorporated herein by reference.
6 # GNU General Public License version 2, incorporated herein by reference.
7
7
8 """Utility functions that use win32 API.
8 """Utility functions that use win32 API.
9
9
10 Mark Hammond's win32all package allows better functionality on
10 Mark Hammond's win32all package allows better functionality on
11 Windows. This module overrides definitions in util.py. If not
11 Windows. This module overrides definitions in util.py. If not
12 available, import of this module will fail, and generic code will be
12 available, import of this module will fail, and generic code will be
13 used.
13 used.
14 """
14 """
15
15
16 import win32api
16 import win32api
17
17
18 import errno, os, sys, pywintypes, win32con, win32file, win32process
18 import errno, os, sys, pywintypes, win32con, win32file, win32process
19 import cStringIO, winerror
19 import cStringIO, winerror
20 import osutil, encoding
20 import osutil, encoding
21 import util
21 import util
22 from win32com.shell import shell,shellcon
22 from win32com.shell import shell,shellcon
23
23
24 class WinError(Exception):
24 class WinError(Exception):
25 winerror_map = {
25 winerror_map = {
26 winerror.ERROR_ACCESS_DENIED: errno.EACCES,
26 winerror.ERROR_ACCESS_DENIED: errno.EACCES,
27 winerror.ERROR_ACCOUNT_DISABLED: errno.EACCES,
27 winerror.ERROR_ACCOUNT_DISABLED: errno.EACCES,
28 winerror.ERROR_ACCOUNT_RESTRICTION: errno.EACCES,
28 winerror.ERROR_ACCOUNT_RESTRICTION: errno.EACCES,
29 winerror.ERROR_ALREADY_ASSIGNED: errno.EBUSY,
29 winerror.ERROR_ALREADY_ASSIGNED: errno.EBUSY,
30 winerror.ERROR_ALREADY_EXISTS: errno.EEXIST,
30 winerror.ERROR_ALREADY_EXISTS: errno.EEXIST,
31 winerror.ERROR_ARITHMETIC_OVERFLOW: errno.ERANGE,
31 winerror.ERROR_ARITHMETIC_OVERFLOW: errno.ERANGE,
32 winerror.ERROR_BAD_COMMAND: errno.EIO,
32 winerror.ERROR_BAD_COMMAND: errno.EIO,
33 winerror.ERROR_BAD_DEVICE: errno.ENODEV,
33 winerror.ERROR_BAD_DEVICE: errno.ENODEV,
34 winerror.ERROR_BAD_DRIVER_LEVEL: errno.ENXIO,
34 winerror.ERROR_BAD_DRIVER_LEVEL: errno.ENXIO,
35 winerror.ERROR_BAD_EXE_FORMAT: errno.ENOEXEC,
35 winerror.ERROR_BAD_EXE_FORMAT: errno.ENOEXEC,
36 winerror.ERROR_BAD_FORMAT: errno.ENOEXEC,
36 winerror.ERROR_BAD_FORMAT: errno.ENOEXEC,
37 winerror.ERROR_BAD_LENGTH: errno.EINVAL,
37 winerror.ERROR_BAD_LENGTH: errno.EINVAL,
38 winerror.ERROR_BAD_PATHNAME: errno.ENOENT,
38 winerror.ERROR_BAD_PATHNAME: errno.ENOENT,
39 winerror.ERROR_BAD_PIPE: errno.EPIPE,
39 winerror.ERROR_BAD_PIPE: errno.EPIPE,
40 winerror.ERROR_BAD_UNIT: errno.ENODEV,
40 winerror.ERROR_BAD_UNIT: errno.ENODEV,
41 winerror.ERROR_BAD_USERNAME: errno.EINVAL,
41 winerror.ERROR_BAD_USERNAME: errno.EINVAL,
42 winerror.ERROR_BROKEN_PIPE: errno.EPIPE,
42 winerror.ERROR_BROKEN_PIPE: errno.EPIPE,
43 winerror.ERROR_BUFFER_OVERFLOW: errno.ENAMETOOLONG,
43 winerror.ERROR_BUFFER_OVERFLOW: errno.ENAMETOOLONG,
44 winerror.ERROR_BUSY: errno.EBUSY,
44 winerror.ERROR_BUSY: errno.EBUSY,
45 winerror.ERROR_BUSY_DRIVE: errno.EBUSY,
45 winerror.ERROR_BUSY_DRIVE: errno.EBUSY,
46 winerror.ERROR_CALL_NOT_IMPLEMENTED: errno.ENOSYS,
46 winerror.ERROR_CALL_NOT_IMPLEMENTED: errno.ENOSYS,
47 winerror.ERROR_CANNOT_MAKE: errno.EACCES,
47 winerror.ERROR_CANNOT_MAKE: errno.EACCES,
48 winerror.ERROR_CANTOPEN: errno.EIO,
48 winerror.ERROR_CANTOPEN: errno.EIO,
49 winerror.ERROR_CANTREAD: errno.EIO,
49 winerror.ERROR_CANTREAD: errno.EIO,
50 winerror.ERROR_CANTWRITE: errno.EIO,
50 winerror.ERROR_CANTWRITE: errno.EIO,
51 winerror.ERROR_CRC: errno.EIO,
51 winerror.ERROR_CRC: errno.EIO,
52 winerror.ERROR_CURRENT_DIRECTORY: errno.EACCES,
52 winerror.ERROR_CURRENT_DIRECTORY: errno.EACCES,
53 winerror.ERROR_DEVICE_IN_USE: errno.EBUSY,
53 winerror.ERROR_DEVICE_IN_USE: errno.EBUSY,
54 winerror.ERROR_DEV_NOT_EXIST: errno.ENODEV,
54 winerror.ERROR_DEV_NOT_EXIST: errno.ENODEV,
55 winerror.ERROR_DIRECTORY: errno.EINVAL,
55 winerror.ERROR_DIRECTORY: errno.EINVAL,
56 winerror.ERROR_DIR_NOT_EMPTY: errno.ENOTEMPTY,
56 winerror.ERROR_DIR_NOT_EMPTY: errno.ENOTEMPTY,
57 winerror.ERROR_DISK_CHANGE: errno.EIO,
57 winerror.ERROR_DISK_CHANGE: errno.EIO,
58 winerror.ERROR_DISK_FULL: errno.ENOSPC,
58 winerror.ERROR_DISK_FULL: errno.ENOSPC,
59 winerror.ERROR_DRIVE_LOCKED: errno.EBUSY,
59 winerror.ERROR_DRIVE_LOCKED: errno.EBUSY,
60 winerror.ERROR_ENVVAR_NOT_FOUND: errno.EINVAL,
60 winerror.ERROR_ENVVAR_NOT_FOUND: errno.EINVAL,
61 winerror.ERROR_EXE_MARKED_INVALID: errno.ENOEXEC,
61 winerror.ERROR_EXE_MARKED_INVALID: errno.ENOEXEC,
62 winerror.ERROR_FILENAME_EXCED_RANGE: errno.ENAMETOOLONG,
62 winerror.ERROR_FILENAME_EXCED_RANGE: errno.ENAMETOOLONG,
63 winerror.ERROR_FILE_EXISTS: errno.EEXIST,
63 winerror.ERROR_FILE_EXISTS: errno.EEXIST,
64 winerror.ERROR_FILE_INVALID: errno.ENODEV,
64 winerror.ERROR_FILE_INVALID: errno.ENODEV,
65 winerror.ERROR_FILE_NOT_FOUND: errno.ENOENT,
65 winerror.ERROR_FILE_NOT_FOUND: errno.ENOENT,
66 winerror.ERROR_GEN_FAILURE: errno.EIO,
66 winerror.ERROR_GEN_FAILURE: errno.EIO,
67 winerror.ERROR_HANDLE_DISK_FULL: errno.ENOSPC,
67 winerror.ERROR_HANDLE_DISK_FULL: errno.ENOSPC,
68 winerror.ERROR_INSUFFICIENT_BUFFER: errno.ENOMEM,
68 winerror.ERROR_INSUFFICIENT_BUFFER: errno.ENOMEM,
69 winerror.ERROR_INVALID_ACCESS: errno.EACCES,
69 winerror.ERROR_INVALID_ACCESS: errno.EACCES,
70 winerror.ERROR_INVALID_ADDRESS: errno.EFAULT,
70 winerror.ERROR_INVALID_ADDRESS: errno.EFAULT,
71 winerror.ERROR_INVALID_BLOCK: errno.EFAULT,
71 winerror.ERROR_INVALID_BLOCK: errno.EFAULT,
72 winerror.ERROR_INVALID_DATA: errno.EINVAL,
72 winerror.ERROR_INVALID_DATA: errno.EINVAL,
73 winerror.ERROR_INVALID_DRIVE: errno.ENODEV,
73 winerror.ERROR_INVALID_DRIVE: errno.ENODEV,
74 winerror.ERROR_INVALID_EXE_SIGNATURE: errno.ENOEXEC,
74 winerror.ERROR_INVALID_EXE_SIGNATURE: errno.ENOEXEC,
75 winerror.ERROR_INVALID_FLAGS: errno.EINVAL,
75 winerror.ERROR_INVALID_FLAGS: errno.EINVAL,
76 winerror.ERROR_INVALID_FUNCTION: errno.ENOSYS,
76 winerror.ERROR_INVALID_FUNCTION: errno.ENOSYS,
77 winerror.ERROR_INVALID_HANDLE: errno.EBADF,
77 winerror.ERROR_INVALID_HANDLE: errno.EBADF,
78 winerror.ERROR_INVALID_LOGON_HOURS: errno.EACCES,
78 winerror.ERROR_INVALID_LOGON_HOURS: errno.EACCES,
79 winerror.ERROR_INVALID_NAME: errno.EINVAL,
79 winerror.ERROR_INVALID_NAME: errno.EINVAL,
80 winerror.ERROR_INVALID_OWNER: errno.EINVAL,
80 winerror.ERROR_INVALID_OWNER: errno.EINVAL,
81 winerror.ERROR_INVALID_PARAMETER: errno.EINVAL,
81 winerror.ERROR_INVALID_PARAMETER: errno.EINVAL,
82 winerror.ERROR_INVALID_PASSWORD: errno.EPERM,
82 winerror.ERROR_INVALID_PASSWORD: errno.EPERM,
83 winerror.ERROR_INVALID_PRIMARY_GROUP: errno.EINVAL,
83 winerror.ERROR_INVALID_PRIMARY_GROUP: errno.EINVAL,
84 winerror.ERROR_INVALID_SIGNAL_NUMBER: errno.EINVAL,
84 winerror.ERROR_INVALID_SIGNAL_NUMBER: errno.EINVAL,
85 winerror.ERROR_INVALID_TARGET_HANDLE: errno.EIO,
85 winerror.ERROR_INVALID_TARGET_HANDLE: errno.EIO,
86 winerror.ERROR_INVALID_WORKSTATION: errno.EACCES,
86 winerror.ERROR_INVALID_WORKSTATION: errno.EACCES,
87 winerror.ERROR_IO_DEVICE: errno.EIO,
87 winerror.ERROR_IO_DEVICE: errno.EIO,
88 winerror.ERROR_IO_INCOMPLETE: errno.EINTR,
88 winerror.ERROR_IO_INCOMPLETE: errno.EINTR,
89 winerror.ERROR_LOCKED: errno.EBUSY,
89 winerror.ERROR_LOCKED: errno.EBUSY,
90 winerror.ERROR_LOCK_VIOLATION: errno.EACCES,
90 winerror.ERROR_LOCK_VIOLATION: errno.EACCES,
91 winerror.ERROR_LOGON_FAILURE: errno.EACCES,
91 winerror.ERROR_LOGON_FAILURE: errno.EACCES,
92 winerror.ERROR_MAPPED_ALIGNMENT: errno.EINVAL,
92 winerror.ERROR_MAPPED_ALIGNMENT: errno.EINVAL,
93 winerror.ERROR_META_EXPANSION_TOO_LONG: errno.E2BIG,
93 winerror.ERROR_META_EXPANSION_TOO_LONG: errno.E2BIG,
94 winerror.ERROR_MORE_DATA: errno.EPIPE,
94 winerror.ERROR_MORE_DATA: errno.EPIPE,
95 winerror.ERROR_NEGATIVE_SEEK: errno.ESPIPE,
95 winerror.ERROR_NEGATIVE_SEEK: errno.ESPIPE,
96 winerror.ERROR_NOACCESS: errno.EFAULT,
96 winerror.ERROR_NOACCESS: errno.EFAULT,
97 winerror.ERROR_NONE_MAPPED: errno.EINVAL,
97 winerror.ERROR_NONE_MAPPED: errno.EINVAL,
98 winerror.ERROR_NOT_ENOUGH_MEMORY: errno.ENOMEM,
98 winerror.ERROR_NOT_ENOUGH_MEMORY: errno.ENOMEM,
99 winerror.ERROR_NOT_READY: errno.EAGAIN,
99 winerror.ERROR_NOT_READY: errno.EAGAIN,
100 winerror.ERROR_NOT_SAME_DEVICE: errno.EXDEV,
100 winerror.ERROR_NOT_SAME_DEVICE: errno.EXDEV,
101 winerror.ERROR_NO_DATA: errno.EPIPE,
101 winerror.ERROR_NO_DATA: errno.EPIPE,
102 winerror.ERROR_NO_MORE_SEARCH_HANDLES: errno.EIO,
102 winerror.ERROR_NO_MORE_SEARCH_HANDLES: errno.EIO,
103 winerror.ERROR_NO_PROC_SLOTS: errno.EAGAIN,
103 winerror.ERROR_NO_PROC_SLOTS: errno.EAGAIN,
104 winerror.ERROR_NO_SUCH_PRIVILEGE: errno.EACCES,
104 winerror.ERROR_NO_SUCH_PRIVILEGE: errno.EACCES,
105 winerror.ERROR_OPEN_FAILED: errno.EIO,
105 winerror.ERROR_OPEN_FAILED: errno.EIO,
106 winerror.ERROR_OPEN_FILES: errno.EBUSY,
106 winerror.ERROR_OPEN_FILES: errno.EBUSY,
107 winerror.ERROR_OPERATION_ABORTED: errno.EINTR,
107 winerror.ERROR_OPERATION_ABORTED: errno.EINTR,
108 winerror.ERROR_OUTOFMEMORY: errno.ENOMEM,
108 winerror.ERROR_OUTOFMEMORY: errno.ENOMEM,
109 winerror.ERROR_PASSWORD_EXPIRED: errno.EACCES,
109 winerror.ERROR_PASSWORD_EXPIRED: errno.EACCES,
110 winerror.ERROR_PATH_BUSY: errno.EBUSY,
110 winerror.ERROR_PATH_BUSY: errno.EBUSY,
111 winerror.ERROR_PATH_NOT_FOUND: errno.ENOENT,
111 winerror.ERROR_PATH_NOT_FOUND: errno.ENOENT,
112 winerror.ERROR_PIPE_BUSY: errno.EBUSY,
112 winerror.ERROR_PIPE_BUSY: errno.EBUSY,
113 winerror.ERROR_PIPE_CONNECTED: errno.EPIPE,
113 winerror.ERROR_PIPE_CONNECTED: errno.EPIPE,
114 winerror.ERROR_PIPE_LISTENING: errno.EPIPE,
114 winerror.ERROR_PIPE_LISTENING: errno.EPIPE,
115 winerror.ERROR_PIPE_NOT_CONNECTED: errno.EPIPE,
115 winerror.ERROR_PIPE_NOT_CONNECTED: errno.EPIPE,
116 winerror.ERROR_PRIVILEGE_NOT_HELD: errno.EACCES,
116 winerror.ERROR_PRIVILEGE_NOT_HELD: errno.EACCES,
117 winerror.ERROR_READ_FAULT: errno.EIO,
117 winerror.ERROR_READ_FAULT: errno.EIO,
118 winerror.ERROR_SEEK: errno.EIO,
118 winerror.ERROR_SEEK: errno.EIO,
119 winerror.ERROR_SEEK_ON_DEVICE: errno.ESPIPE,
119 winerror.ERROR_SEEK_ON_DEVICE: errno.ESPIPE,
120 winerror.ERROR_SHARING_BUFFER_EXCEEDED: errno.ENFILE,
120 winerror.ERROR_SHARING_BUFFER_EXCEEDED: errno.ENFILE,
121 winerror.ERROR_SHARING_VIOLATION: errno.EACCES,
121 winerror.ERROR_SHARING_VIOLATION: errno.EACCES,
122 winerror.ERROR_STACK_OVERFLOW: errno.ENOMEM,
122 winerror.ERROR_STACK_OVERFLOW: errno.ENOMEM,
123 winerror.ERROR_SWAPERROR: errno.ENOENT,
123 winerror.ERROR_SWAPERROR: errno.ENOENT,
124 winerror.ERROR_TOO_MANY_MODULES: errno.EMFILE,
124 winerror.ERROR_TOO_MANY_MODULES: errno.EMFILE,
125 winerror.ERROR_TOO_MANY_OPEN_FILES: errno.EMFILE,
125 winerror.ERROR_TOO_MANY_OPEN_FILES: errno.EMFILE,
126 winerror.ERROR_UNRECOGNIZED_MEDIA: errno.ENXIO,
126 winerror.ERROR_UNRECOGNIZED_MEDIA: errno.ENXIO,
127 winerror.ERROR_UNRECOGNIZED_VOLUME: errno.ENODEV,
127 winerror.ERROR_UNRECOGNIZED_VOLUME: errno.ENODEV,
128 winerror.ERROR_WAIT_NO_CHILDREN: errno.ECHILD,
128 winerror.ERROR_WAIT_NO_CHILDREN: errno.ECHILD,
129 winerror.ERROR_WRITE_FAULT: errno.EIO,
129 winerror.ERROR_WRITE_FAULT: errno.EIO,
130 winerror.ERROR_WRITE_PROTECT: errno.EROFS,
130 winerror.ERROR_WRITE_PROTECT: errno.EROFS,
131 }
131 }
132
132
133 def __init__(self, err):
133 def __init__(self, err):
134 self.win_errno, self.win_function, self.win_strerror = err
134 try:
135 if self.win_strerror.endswith('.'):
135 # unpack a pywintypes.error tuple
136 self.win_strerror = self.win_strerror[:-1]
136 self.win_errno, self.win_function, self.win_strerror = err
137 except ValueError:
138 # get attributes from a WindowsError
139 self.win_errno = err.winerror
140 self.win_function = None
141 self.win_strerror = err.strerror
142 self.win_strerror = self.win_strerror.rstrip('.')
137
143
138 class WinIOError(WinError, IOError):
144 class WinIOError(WinError, IOError):
139 def __init__(self, err, filename=None):
145 def __init__(self, err, filename=None):
140 WinError.__init__(self, err)
146 WinError.__init__(self, err)
141 IOError.__init__(self, self.winerror_map.get(self.win_errno, 0),
147 IOError.__init__(self, self.winerror_map.get(self.win_errno, 0),
142 self.win_strerror)
148 self.win_strerror)
143 self.filename = filename
149 self.filename = filename
144
150
145 class WinOSError(WinError, OSError):
151 class WinOSError(WinError, OSError):
146 def __init__(self, err):
152 def __init__(self, err):
147 WinError.__init__(self, err)
153 WinError.__init__(self, err)
148 OSError.__init__(self, self.winerror_map.get(self.win_errno, 0),
154 OSError.__init__(self, self.winerror_map.get(self.win_errno, 0),
149 self.win_strerror)
155 self.win_strerror)
150
156
151 def os_link(src, dst):
157 def os_link(src, dst):
152 try:
158 try:
153 win32file.CreateHardLink(dst, src)
159 win32file.CreateHardLink(dst, src)
154 # CreateHardLink sometimes succeeds on mapped drives but
160 # CreateHardLink sometimes succeeds on mapped drives but
155 # following nlinks() returns 1. Check it now and bail out.
161 # following nlinks() returns 1. Check it now and bail out.
156 if nlinks(src) < 2:
162 if nlinks(src) < 2:
157 try:
163 try:
158 win32file.DeleteFile(dst)
164 win32file.DeleteFile(dst)
159 except:
165 except:
160 pass
166 pass
161 # Fake hardlinking error
167 # Fake hardlinking error
162 raise WinOSError((18, 'CreateHardLink', 'The system cannot '
168 raise WinOSError((18, 'CreateHardLink', 'The system cannot '
163 'move the file to a different disk drive'))
169 'move the file to a different disk drive'))
164 except pywintypes.error, details:
170 except pywintypes.error, details:
165 raise WinOSError(details)
171 raise WinOSError(details)
166 except NotImplementedError: # Another fake error win Win98
172 except NotImplementedError: # Another fake error win Win98
167 raise WinOSError((18, 'CreateHardLink', 'Hardlinking not supported'))
173 raise WinOSError((18, 'CreateHardLink', 'Hardlinking not supported'))
168
174
169 def nlinks(pathname):
175 def nlinks(pathname):
170 """Return number of hardlinks for the given file."""
176 """Return number of hardlinks for the given file."""
171 try:
177 try:
172 fh = win32file.CreateFile(pathname,
178 fh = win32file.CreateFile(pathname,
173 win32file.GENERIC_READ, win32file.FILE_SHARE_READ,
179 win32file.GENERIC_READ, win32file.FILE_SHARE_READ,
174 None, win32file.OPEN_EXISTING, 0, None)
180 None, win32file.OPEN_EXISTING, 0, None)
175 res = win32file.GetFileInformationByHandle(fh)
181 res = win32file.GetFileInformationByHandle(fh)
176 fh.Close()
182 fh.Close()
177 return res[7]
183 return res[7]
178 except pywintypes.error:
184 except pywintypes.error:
179 return os.lstat(pathname).st_nlink
185 return os.lstat(pathname).st_nlink
180
186
181 def testpid(pid):
187 def testpid(pid):
182 '''return True if pid is still running or unable to
188 '''return True if pid is still running or unable to
183 determine, False otherwise'''
189 determine, False otherwise'''
184 try:
190 try:
185 handle = win32api.OpenProcess(
191 handle = win32api.OpenProcess(
186 win32con.PROCESS_QUERY_INFORMATION, False, pid)
192 win32con.PROCESS_QUERY_INFORMATION, False, pid)
187 if handle:
193 if handle:
188 status = win32process.GetExitCodeProcess(handle)
194 status = win32process.GetExitCodeProcess(handle)
189 return status == win32con.STILL_ACTIVE
195 return status == win32con.STILL_ACTIVE
190 except pywintypes.error, details:
196 except pywintypes.error, details:
191 return details[0] != winerror.ERROR_INVALID_PARAMETER
197 return details[0] != winerror.ERROR_INVALID_PARAMETER
192 return True
198 return True
193
199
194 def lookup_reg(key, valname=None, scope=None):
200 def lookup_reg(key, valname=None, scope=None):
195 ''' Look up a key/value name in the Windows registry.
201 ''' Look up a key/value name in the Windows registry.
196
202
197 valname: value name. If unspecified, the default value for the key
203 valname: value name. If unspecified, the default value for the key
198 is used.
204 is used.
199 scope: optionally specify scope for registry lookup, this can be
205 scope: optionally specify scope for registry lookup, this can be
200 a sequence of scopes to look up in order. Default (CURRENT_USER,
206 a sequence of scopes to look up in order. Default (CURRENT_USER,
201 LOCAL_MACHINE).
207 LOCAL_MACHINE).
202 '''
208 '''
203 try:
209 try:
204 from _winreg import HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, \
210 from _winreg import HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, \
205 QueryValueEx, OpenKey
211 QueryValueEx, OpenKey
206 except ImportError:
212 except ImportError:
207 return None
213 return None
208
214
209 if scope is None:
215 if scope is None:
210 scope = (HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE)
216 scope = (HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE)
211 elif not isinstance(scope, (list, tuple)):
217 elif not isinstance(scope, (list, tuple)):
212 scope = (scope,)
218 scope = (scope,)
213 for s in scope:
219 for s in scope:
214 try:
220 try:
215 val = QueryValueEx(OpenKey(s, key), valname)[0]
221 val = QueryValueEx(OpenKey(s, key), valname)[0]
216 # never let a Unicode string escape into the wild
222 # never let a Unicode string escape into the wild
217 return encoding.tolocal(val.encode('UTF-8'))
223 return encoding.tolocal(val.encode('UTF-8'))
218 except EnvironmentError:
224 except EnvironmentError:
219 pass
225 pass
220
226
221 def system_rcpath_win32():
227 def system_rcpath_win32():
222 '''return default os-specific hgrc search path'''
228 '''return default os-specific hgrc search path'''
223 proc = win32api.GetCurrentProcess()
229 proc = win32api.GetCurrentProcess()
224 try:
230 try:
225 # This will fail on windows < NT
231 # This will fail on windows < NT
226 filename = win32process.GetModuleFileNameEx(proc, 0)
232 filename = win32process.GetModuleFileNameEx(proc, 0)
227 except:
233 except:
228 filename = win32api.GetModuleFileName(0)
234 filename = win32api.GetModuleFileName(0)
229 # Use mercurial.ini found in directory with hg.exe
235 # Use mercurial.ini found in directory with hg.exe
230 progrc = os.path.join(os.path.dirname(filename), 'mercurial.ini')
236 progrc = os.path.join(os.path.dirname(filename), 'mercurial.ini')
231 if os.path.isfile(progrc):
237 if os.path.isfile(progrc):
232 return [progrc]
238 return [progrc]
233 # else look for a system rcpath in the registry
239 # else look for a system rcpath in the registry
234 try:
240 try:
235 value = win32api.RegQueryValue(
241 value = win32api.RegQueryValue(
236 win32con.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Mercurial')
242 win32con.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Mercurial')
237 rcpath = []
243 rcpath = []
238 for p in value.split(os.pathsep):
244 for p in value.split(os.pathsep):
239 if p.lower().endswith('mercurial.ini'):
245 if p.lower().endswith('mercurial.ini'):
240 rcpath.append(p)
246 rcpath.append(p)
241 elif os.path.isdir(p):
247 elif os.path.isdir(p):
242 for f, kind in osutil.listdir(p):
248 for f, kind in osutil.listdir(p):
243 if f.endswith('.rc'):
249 if f.endswith('.rc'):
244 rcpath.append(os.path.join(p, f))
250 rcpath.append(os.path.join(p, f))
245 return rcpath
251 return rcpath
246 except pywintypes.error:
252 except pywintypes.error:
247 return []
253 return []
248
254
249 def user_rcpath_win32():
255 def user_rcpath_win32():
250 '''return os-specific hgrc search path to the user dir'''
256 '''return os-specific hgrc search path to the user dir'''
251 userdir = os.path.expanduser('~')
257 userdir = os.path.expanduser('~')
252 if sys.getwindowsversion()[3] != 2 and userdir == '~':
258 if sys.getwindowsversion()[3] != 2 and userdir == '~':
253 # We are on win < nt: fetch the APPDATA directory location and use
259 # We are on win < nt: fetch the APPDATA directory location and use
254 # the parent directory as the user home dir.
260 # the parent directory as the user home dir.
255 appdir = shell.SHGetPathFromIDList(
261 appdir = shell.SHGetPathFromIDList(
256 shell.SHGetSpecialFolderLocation(0, shellcon.CSIDL_APPDATA))
262 shell.SHGetSpecialFolderLocation(0, shellcon.CSIDL_APPDATA))
257 userdir = os.path.dirname(appdir)
263 userdir = os.path.dirname(appdir)
258 return [os.path.join(userdir, 'mercurial.ini'),
264 return [os.path.join(userdir, 'mercurial.ini'),
259 os.path.join(userdir, '.hgrc')]
265 os.path.join(userdir, '.hgrc')]
260
266
261 class posixfile_nt(object):
267 class posixfile_nt(object):
262 '''file object with posix-like semantics. on windows, normal
268 '''file object with posix-like semantics. on windows, normal
263 files can not be deleted or renamed if they are open. must open
269 files can not be deleted or renamed if they are open. must open
264 with win32file.FILE_SHARE_DELETE. this flag does not exist on
270 with win32file.FILE_SHARE_DELETE. this flag does not exist on
265 windows < nt, so do not use this class there.'''
271 windows < nt, so do not use this class there.'''
266
272
267 # tried to use win32file._open_osfhandle to pass fd to os.fdopen,
273 # tried to use win32file._open_osfhandle to pass fd to os.fdopen,
268 # but does not work at all. wrap win32 file api instead.
274 # but does not work at all. wrap win32 file api instead.
269
275
270 def __init__(self, name, mode='rb'):
276 def __init__(self, name, mode='rb'):
271 self.closed = False
277 self.closed = False
272 self.name = name
278 self.name = name
273 self.mode = mode
279 self.mode = mode
274 access = 0
280 access = 0
275 if 'r' in mode or '+' in mode:
281 if 'r' in mode or '+' in mode:
276 access |= win32file.GENERIC_READ
282 access |= win32file.GENERIC_READ
277 if 'w' in mode or 'a' in mode or '+' in mode:
283 if 'w' in mode or 'a' in mode or '+' in mode:
278 access |= win32file.GENERIC_WRITE
284 access |= win32file.GENERIC_WRITE
279 if 'r' in mode:
285 if 'r' in mode:
280 creation = win32file.OPEN_EXISTING
286 creation = win32file.OPEN_EXISTING
281 elif 'a' in mode:
287 elif 'a' in mode:
282 creation = win32file.OPEN_ALWAYS
288 creation = win32file.OPEN_ALWAYS
283 else:
289 else:
284 creation = win32file.CREATE_ALWAYS
290 creation = win32file.CREATE_ALWAYS
285 try:
291 try:
286 self.handle = win32file.CreateFile(name,
292 self.handle = win32file.CreateFile(name,
287 access,
293 access,
288 win32file.FILE_SHARE_READ |
294 win32file.FILE_SHARE_READ |
289 win32file.FILE_SHARE_WRITE |
295 win32file.FILE_SHARE_WRITE |
290 win32file.FILE_SHARE_DELETE,
296 win32file.FILE_SHARE_DELETE,
291 None,
297 None,
292 creation,
298 creation,
293 win32file.FILE_ATTRIBUTE_NORMAL,
299 win32file.FILE_ATTRIBUTE_NORMAL,
294 0)
300 0)
295 except pywintypes.error, err:
301 except pywintypes.error, err:
296 raise WinIOError(err, name)
302 raise WinIOError(err, name)
297
303
298 def __iter__(self):
304 def __iter__(self):
299 for line in self.readlines():
305 for line in self.readlines():
300 yield line
306 yield line
301
307
302 def read(self, count=-1):
308 def read(self, count=-1):
303 try:
309 try:
304 cs = cStringIO.StringIO()
310 cs = cStringIO.StringIO()
305 while count:
311 while count:
306 wincount = int(count)
312 wincount = int(count)
307 if wincount == -1:
313 if wincount == -1:
308 wincount = 1048576
314 wincount = 1048576
309 val, data = win32file.ReadFile(self.handle, wincount)
315 val, data = win32file.ReadFile(self.handle, wincount)
310 if not data: break
316 if not data: break
311 cs.write(data)
317 cs.write(data)
312 if count != -1:
318 if count != -1:
313 count -= len(data)
319 count -= len(data)
314 return cs.getvalue()
320 return cs.getvalue()
315 except pywintypes.error, err:
321 except pywintypes.error, err:
316 raise WinIOError(err)
322 raise WinIOError(err)
317
323
318 def readlines(self, sizehint=None):
324 def readlines(self, sizehint=None):
319 # splitlines() splits on single '\r' while readlines()
325 # splitlines() splits on single '\r' while readlines()
320 # does not. cStringIO has a well behaving readlines() and is fast.
326 # does not. cStringIO has a well behaving readlines() and is fast.
321 return cStringIO.StringIO(self.read()).readlines()
327 return cStringIO.StringIO(self.read()).readlines()
322
328
323 def write(self, data):
329 def write(self, data):
324 try:
330 try:
325 if 'a' in self.mode:
331 if 'a' in self.mode:
326 win32file.SetFilePointer(self.handle, 0, win32file.FILE_END)
332 win32file.SetFilePointer(self.handle, 0, win32file.FILE_END)
327 nwrit = 0
333 nwrit = 0
328 while nwrit < len(data):
334 while nwrit < len(data):
329 val, nwrit = win32file.WriteFile(self.handle, data)
335 val, nwrit = win32file.WriteFile(self.handle, data)
330 data = data[nwrit:]
336 data = data[nwrit:]
331 except pywintypes.error, err:
337 except pywintypes.error, err:
332 raise WinIOError(err)
338 raise WinIOError(err)
333
339
334 def writelines(self, sequence):
340 def writelines(self, sequence):
335 for s in sequence:
341 for s in sequence:
336 self.write(s)
342 self.write(s)
337
343
338 def seek(self, pos, whence=0):
344 def seek(self, pos, whence=0):
339 try:
345 try:
340 win32file.SetFilePointer(self.handle, int(pos), whence)
346 win32file.SetFilePointer(self.handle, int(pos), whence)
341 except pywintypes.error, err:
347 except pywintypes.error, err:
342 raise WinIOError(err)
348 raise WinIOError(err)
343
349
344 def tell(self):
350 def tell(self):
345 try:
351 try:
346 return win32file.SetFilePointer(self.handle, 0,
352 return win32file.SetFilePointer(self.handle, 0,
347 win32file.FILE_CURRENT)
353 win32file.FILE_CURRENT)
348 except pywintypes.error, err:
354 except pywintypes.error, err:
349 raise WinIOError(err)
355 raise WinIOError(err)
350
356
351 def close(self):
357 def close(self):
352 if not self.closed:
358 if not self.closed:
353 self.handle = None
359 self.handle = None
354 self.closed = True
360 self.closed = True
355
361
356 def flush(self):
362 def flush(self):
357 # we have no application-level buffering
363 # we have no application-level buffering
358 pass
364 pass
359
365
360 def truncate(self, pos=0):
366 def truncate(self, pos=0):
361 try:
367 try:
362 win32file.SetFilePointer(self.handle, int(pos),
368 win32file.SetFilePointer(self.handle, int(pos),
363 win32file.FILE_BEGIN)
369 win32file.FILE_BEGIN)
364 win32file.SetEndOfFile(self.handle)
370 win32file.SetEndOfFile(self.handle)
365 except pywintypes.error, err:
371 except pywintypes.error, err:
366 raise WinIOError(err)
372 raise WinIOError(err)
367
373
368 def getuser():
374 def getuser():
369 '''return name of current user'''
375 '''return name of current user'''
370 return win32api.GetUserName()
376 return win32api.GetUserName()
371
377
372 def set_signal_handler_win32():
378 def set_signal_handler_win32():
373 """Register a termination handler for console events including
379 """Register a termination handler for console events including
374 CTRL+C. python signal handlers do not work well with socket
380 CTRL+C. python signal handlers do not work well with socket
375 operations.
381 operations.
376 """
382 """
377 def handler(event):
383 def handler(event):
378 win32process.ExitProcess(1)
384 win32process.ExitProcess(1)
379 win32api.SetConsoleCtrlHandler(handler)
385 win32api.SetConsoleCtrlHandler(handler)
380
386
General Comments 0
You need to be logged in to leave comments. Login now