##// END OF EJS Templates
win32: use absolute_import
Gregory Szorc -
r25994:d6beeb61 default
parent child Browse files
Show More
@@ -1,494 +1,501 b''
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 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 import ctypes, errno, msvcrt, os, subprocess, random
8 from __future__ import absolute_import
9
10 import ctypes
11 import errno
12 import msvcrt
13 import os
14 import random
15 import subprocess
9
16
10 _kernel32 = ctypes.windll.kernel32
17 _kernel32 = ctypes.windll.kernel32
11 _advapi32 = ctypes.windll.advapi32
18 _advapi32 = ctypes.windll.advapi32
12 _user32 = ctypes.windll.user32
19 _user32 = ctypes.windll.user32
13
20
14 _BOOL = ctypes.c_long
21 _BOOL = ctypes.c_long
15 _WORD = ctypes.c_ushort
22 _WORD = ctypes.c_ushort
16 _DWORD = ctypes.c_ulong
23 _DWORD = ctypes.c_ulong
17 _UINT = ctypes.c_uint
24 _UINT = ctypes.c_uint
18 _LONG = ctypes.c_long
25 _LONG = ctypes.c_long
19 _LPCSTR = _LPSTR = ctypes.c_char_p
26 _LPCSTR = _LPSTR = ctypes.c_char_p
20 _HANDLE = ctypes.c_void_p
27 _HANDLE = ctypes.c_void_p
21 _HWND = _HANDLE
28 _HWND = _HANDLE
22
29
23 _INVALID_HANDLE_VALUE = _HANDLE(-1).value
30 _INVALID_HANDLE_VALUE = _HANDLE(-1).value
24
31
25 # GetLastError
32 # GetLastError
26 _ERROR_SUCCESS = 0
33 _ERROR_SUCCESS = 0
27 _ERROR_NO_MORE_FILES = 18
34 _ERROR_NO_MORE_FILES = 18
28 _ERROR_INVALID_PARAMETER = 87
35 _ERROR_INVALID_PARAMETER = 87
29 _ERROR_BROKEN_PIPE = 109
36 _ERROR_BROKEN_PIPE = 109
30 _ERROR_INSUFFICIENT_BUFFER = 122
37 _ERROR_INSUFFICIENT_BUFFER = 122
31
38
32 # WPARAM is defined as UINT_PTR (unsigned type)
39 # WPARAM is defined as UINT_PTR (unsigned type)
33 # LPARAM is defined as LONG_PTR (signed type)
40 # LPARAM is defined as LONG_PTR (signed type)
34 if ctypes.sizeof(ctypes.c_long) == ctypes.sizeof(ctypes.c_void_p):
41 if ctypes.sizeof(ctypes.c_long) == ctypes.sizeof(ctypes.c_void_p):
35 _WPARAM = ctypes.c_ulong
42 _WPARAM = ctypes.c_ulong
36 _LPARAM = ctypes.c_long
43 _LPARAM = ctypes.c_long
37 elif ctypes.sizeof(ctypes.c_longlong) == ctypes.sizeof(ctypes.c_void_p):
44 elif ctypes.sizeof(ctypes.c_longlong) == ctypes.sizeof(ctypes.c_void_p):
38 _WPARAM = ctypes.c_ulonglong
45 _WPARAM = ctypes.c_ulonglong
39 _LPARAM = ctypes.c_longlong
46 _LPARAM = ctypes.c_longlong
40
47
41 class _FILETIME(ctypes.Structure):
48 class _FILETIME(ctypes.Structure):
42 _fields_ = [('dwLowDateTime', _DWORD),
49 _fields_ = [('dwLowDateTime', _DWORD),
43 ('dwHighDateTime', _DWORD)]
50 ('dwHighDateTime', _DWORD)]
44
51
45 class _BY_HANDLE_FILE_INFORMATION(ctypes.Structure):
52 class _BY_HANDLE_FILE_INFORMATION(ctypes.Structure):
46 _fields_ = [('dwFileAttributes', _DWORD),
53 _fields_ = [('dwFileAttributes', _DWORD),
47 ('ftCreationTime', _FILETIME),
54 ('ftCreationTime', _FILETIME),
48 ('ftLastAccessTime', _FILETIME),
55 ('ftLastAccessTime', _FILETIME),
49 ('ftLastWriteTime', _FILETIME),
56 ('ftLastWriteTime', _FILETIME),
50 ('dwVolumeSerialNumber', _DWORD),
57 ('dwVolumeSerialNumber', _DWORD),
51 ('nFileSizeHigh', _DWORD),
58 ('nFileSizeHigh', _DWORD),
52 ('nFileSizeLow', _DWORD),
59 ('nFileSizeLow', _DWORD),
53 ('nNumberOfLinks', _DWORD),
60 ('nNumberOfLinks', _DWORD),
54 ('nFileIndexHigh', _DWORD),
61 ('nFileIndexHigh', _DWORD),
55 ('nFileIndexLow', _DWORD)]
62 ('nFileIndexLow', _DWORD)]
56
63
57 # CreateFile
64 # CreateFile
58 _FILE_SHARE_READ = 0x00000001
65 _FILE_SHARE_READ = 0x00000001
59 _FILE_SHARE_WRITE = 0x00000002
66 _FILE_SHARE_WRITE = 0x00000002
60 _FILE_SHARE_DELETE = 0x00000004
67 _FILE_SHARE_DELETE = 0x00000004
61
68
62 _OPEN_EXISTING = 3
69 _OPEN_EXISTING = 3
63
70
64 _FILE_FLAG_BACKUP_SEMANTICS = 0x02000000
71 _FILE_FLAG_BACKUP_SEMANTICS = 0x02000000
65
72
66 # SetFileAttributes
73 # SetFileAttributes
67 _FILE_ATTRIBUTE_NORMAL = 0x80
74 _FILE_ATTRIBUTE_NORMAL = 0x80
68 _FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x2000
75 _FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x2000
69
76
70 # Process Security and Access Rights
77 # Process Security and Access Rights
71 _PROCESS_QUERY_INFORMATION = 0x0400
78 _PROCESS_QUERY_INFORMATION = 0x0400
72
79
73 # GetExitCodeProcess
80 # GetExitCodeProcess
74 _STILL_ACTIVE = 259
81 _STILL_ACTIVE = 259
75
82
76 class _STARTUPINFO(ctypes.Structure):
83 class _STARTUPINFO(ctypes.Structure):
77 _fields_ = [('cb', _DWORD),
84 _fields_ = [('cb', _DWORD),
78 ('lpReserved', _LPSTR),
85 ('lpReserved', _LPSTR),
79 ('lpDesktop', _LPSTR),
86 ('lpDesktop', _LPSTR),
80 ('lpTitle', _LPSTR),
87 ('lpTitle', _LPSTR),
81 ('dwX', _DWORD),
88 ('dwX', _DWORD),
82 ('dwY', _DWORD),
89 ('dwY', _DWORD),
83 ('dwXSize', _DWORD),
90 ('dwXSize', _DWORD),
84 ('dwYSize', _DWORD),
91 ('dwYSize', _DWORD),
85 ('dwXCountChars', _DWORD),
92 ('dwXCountChars', _DWORD),
86 ('dwYCountChars', _DWORD),
93 ('dwYCountChars', _DWORD),
87 ('dwFillAttribute', _DWORD),
94 ('dwFillAttribute', _DWORD),
88 ('dwFlags', _DWORD),
95 ('dwFlags', _DWORD),
89 ('wShowWindow', _WORD),
96 ('wShowWindow', _WORD),
90 ('cbReserved2', _WORD),
97 ('cbReserved2', _WORD),
91 ('lpReserved2', ctypes.c_char_p),
98 ('lpReserved2', ctypes.c_char_p),
92 ('hStdInput', _HANDLE),
99 ('hStdInput', _HANDLE),
93 ('hStdOutput', _HANDLE),
100 ('hStdOutput', _HANDLE),
94 ('hStdError', _HANDLE)]
101 ('hStdError', _HANDLE)]
95
102
96 class _PROCESS_INFORMATION(ctypes.Structure):
103 class _PROCESS_INFORMATION(ctypes.Structure):
97 _fields_ = [('hProcess', _HANDLE),
104 _fields_ = [('hProcess', _HANDLE),
98 ('hThread', _HANDLE),
105 ('hThread', _HANDLE),
99 ('dwProcessId', _DWORD),
106 ('dwProcessId', _DWORD),
100 ('dwThreadId', _DWORD)]
107 ('dwThreadId', _DWORD)]
101
108
102 _CREATE_NO_WINDOW = 0x08000000
109 _CREATE_NO_WINDOW = 0x08000000
103 _SW_HIDE = 0
110 _SW_HIDE = 0
104
111
105 class _COORD(ctypes.Structure):
112 class _COORD(ctypes.Structure):
106 _fields_ = [('X', ctypes.c_short),
113 _fields_ = [('X', ctypes.c_short),
107 ('Y', ctypes.c_short)]
114 ('Y', ctypes.c_short)]
108
115
109 class _SMALL_RECT(ctypes.Structure):
116 class _SMALL_RECT(ctypes.Structure):
110 _fields_ = [('Left', ctypes.c_short),
117 _fields_ = [('Left', ctypes.c_short),
111 ('Top', ctypes.c_short),
118 ('Top', ctypes.c_short),
112 ('Right', ctypes.c_short),
119 ('Right', ctypes.c_short),
113 ('Bottom', ctypes.c_short)]
120 ('Bottom', ctypes.c_short)]
114
121
115 class _CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure):
122 class _CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure):
116 _fields_ = [('dwSize', _COORD),
123 _fields_ = [('dwSize', _COORD),
117 ('dwCursorPosition', _COORD),
124 ('dwCursorPosition', _COORD),
118 ('wAttributes', _WORD),
125 ('wAttributes', _WORD),
119 ('srWindow', _SMALL_RECT),
126 ('srWindow', _SMALL_RECT),
120 ('dwMaximumWindowSize', _COORD)]
127 ('dwMaximumWindowSize', _COORD)]
121
128
122 _STD_ERROR_HANDLE = _DWORD(-12).value
129 _STD_ERROR_HANDLE = _DWORD(-12).value
123
130
124 # CreateToolhelp32Snapshot, Process32First, Process32Next
131 # CreateToolhelp32Snapshot, Process32First, Process32Next
125 _TH32CS_SNAPPROCESS = 0x00000002
132 _TH32CS_SNAPPROCESS = 0x00000002
126 _MAX_PATH = 260
133 _MAX_PATH = 260
127
134
128 class _tagPROCESSENTRY32(ctypes.Structure):
135 class _tagPROCESSENTRY32(ctypes.Structure):
129 _fields_ = [('dwsize', _DWORD),
136 _fields_ = [('dwsize', _DWORD),
130 ('cntUsage', _DWORD),
137 ('cntUsage', _DWORD),
131 ('th32ProcessID', _DWORD),
138 ('th32ProcessID', _DWORD),
132 ('th32DefaultHeapID', ctypes.c_void_p),
139 ('th32DefaultHeapID', ctypes.c_void_p),
133 ('th32ModuleID', _DWORD),
140 ('th32ModuleID', _DWORD),
134 ('cntThreads', _DWORD),
141 ('cntThreads', _DWORD),
135 ('th32ParentProcessID', _DWORD),
142 ('th32ParentProcessID', _DWORD),
136 ('pcPriClassBase', _LONG),
143 ('pcPriClassBase', _LONG),
137 ('dwFlags', _DWORD),
144 ('dwFlags', _DWORD),
138 ('szExeFile', ctypes.c_char * _MAX_PATH)]
145 ('szExeFile', ctypes.c_char * _MAX_PATH)]
139
146
140 def __init__(self):
147 def __init__(self):
141 super(_tagPROCESSENTRY32, self).__init__()
148 super(_tagPROCESSENTRY32, self).__init__()
142 self.dwsize = ctypes.sizeof(self)
149 self.dwsize = ctypes.sizeof(self)
143
150
144
151
145 # types of parameters of C functions used (required by pypy)
152 # types of parameters of C functions used (required by pypy)
146
153
147 _kernel32.CreateFileA.argtypes = [_LPCSTR, _DWORD, _DWORD, ctypes.c_void_p,
154 _kernel32.CreateFileA.argtypes = [_LPCSTR, _DWORD, _DWORD, ctypes.c_void_p,
148 _DWORD, _DWORD, _HANDLE]
155 _DWORD, _DWORD, _HANDLE]
149 _kernel32.CreateFileA.restype = _HANDLE
156 _kernel32.CreateFileA.restype = _HANDLE
150
157
151 _kernel32.GetFileInformationByHandle.argtypes = [_HANDLE, ctypes.c_void_p]
158 _kernel32.GetFileInformationByHandle.argtypes = [_HANDLE, ctypes.c_void_p]
152 _kernel32.GetFileInformationByHandle.restype = _BOOL
159 _kernel32.GetFileInformationByHandle.restype = _BOOL
153
160
154 _kernel32.CloseHandle.argtypes = [_HANDLE]
161 _kernel32.CloseHandle.argtypes = [_HANDLE]
155 _kernel32.CloseHandle.restype = _BOOL
162 _kernel32.CloseHandle.restype = _BOOL
156
163
157 try:
164 try:
158 _kernel32.CreateHardLinkA.argtypes = [_LPCSTR, _LPCSTR, ctypes.c_void_p]
165 _kernel32.CreateHardLinkA.argtypes = [_LPCSTR, _LPCSTR, ctypes.c_void_p]
159 _kernel32.CreateHardLinkA.restype = _BOOL
166 _kernel32.CreateHardLinkA.restype = _BOOL
160 except AttributeError:
167 except AttributeError:
161 pass
168 pass
162
169
163 _kernel32.SetFileAttributesA.argtypes = [_LPCSTR, _DWORD]
170 _kernel32.SetFileAttributesA.argtypes = [_LPCSTR, _DWORD]
164 _kernel32.SetFileAttributesA.restype = _BOOL
171 _kernel32.SetFileAttributesA.restype = _BOOL
165
172
166 _kernel32.OpenProcess.argtypes = [_DWORD, _BOOL, _DWORD]
173 _kernel32.OpenProcess.argtypes = [_DWORD, _BOOL, _DWORD]
167 _kernel32.OpenProcess.restype = _HANDLE
174 _kernel32.OpenProcess.restype = _HANDLE
168
175
169 _kernel32.GetExitCodeProcess.argtypes = [_HANDLE, ctypes.c_void_p]
176 _kernel32.GetExitCodeProcess.argtypes = [_HANDLE, ctypes.c_void_p]
170 _kernel32.GetExitCodeProcess.restype = _BOOL
177 _kernel32.GetExitCodeProcess.restype = _BOOL
171
178
172 _kernel32.GetLastError.argtypes = []
179 _kernel32.GetLastError.argtypes = []
173 _kernel32.GetLastError.restype = _DWORD
180 _kernel32.GetLastError.restype = _DWORD
174
181
175 _kernel32.GetModuleFileNameA.argtypes = [_HANDLE, ctypes.c_void_p, _DWORD]
182 _kernel32.GetModuleFileNameA.argtypes = [_HANDLE, ctypes.c_void_p, _DWORD]
176 _kernel32.GetModuleFileNameA.restype = _DWORD
183 _kernel32.GetModuleFileNameA.restype = _DWORD
177
184
178 _kernel32.CreateProcessA.argtypes = [_LPCSTR, _LPCSTR, ctypes.c_void_p,
185 _kernel32.CreateProcessA.argtypes = [_LPCSTR, _LPCSTR, ctypes.c_void_p,
179 ctypes.c_void_p, _BOOL, _DWORD, ctypes.c_void_p, _LPCSTR, ctypes.c_void_p,
186 ctypes.c_void_p, _BOOL, _DWORD, ctypes.c_void_p, _LPCSTR, ctypes.c_void_p,
180 ctypes.c_void_p]
187 ctypes.c_void_p]
181 _kernel32.CreateProcessA.restype = _BOOL
188 _kernel32.CreateProcessA.restype = _BOOL
182
189
183 _kernel32.ExitProcess.argtypes = [_UINT]
190 _kernel32.ExitProcess.argtypes = [_UINT]
184 _kernel32.ExitProcess.restype = None
191 _kernel32.ExitProcess.restype = None
185
192
186 _kernel32.GetCurrentProcessId.argtypes = []
193 _kernel32.GetCurrentProcessId.argtypes = []
187 _kernel32.GetCurrentProcessId.restype = _DWORD
194 _kernel32.GetCurrentProcessId.restype = _DWORD
188
195
189 _SIGNAL_HANDLER = ctypes.WINFUNCTYPE(_BOOL, _DWORD)
196 _SIGNAL_HANDLER = ctypes.WINFUNCTYPE(_BOOL, _DWORD)
190 _kernel32.SetConsoleCtrlHandler.argtypes = [_SIGNAL_HANDLER, _BOOL]
197 _kernel32.SetConsoleCtrlHandler.argtypes = [_SIGNAL_HANDLER, _BOOL]
191 _kernel32.SetConsoleCtrlHandler.restype = _BOOL
198 _kernel32.SetConsoleCtrlHandler.restype = _BOOL
192
199
193 _kernel32.GetStdHandle.argtypes = [_DWORD]
200 _kernel32.GetStdHandle.argtypes = [_DWORD]
194 _kernel32.GetStdHandle.restype = _HANDLE
201 _kernel32.GetStdHandle.restype = _HANDLE
195
202
196 _kernel32.GetConsoleScreenBufferInfo.argtypes = [_HANDLE, ctypes.c_void_p]
203 _kernel32.GetConsoleScreenBufferInfo.argtypes = [_HANDLE, ctypes.c_void_p]
197 _kernel32.GetConsoleScreenBufferInfo.restype = _BOOL
204 _kernel32.GetConsoleScreenBufferInfo.restype = _BOOL
198
205
199 _advapi32.GetUserNameA.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
206 _advapi32.GetUserNameA.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
200 _advapi32.GetUserNameA.restype = _BOOL
207 _advapi32.GetUserNameA.restype = _BOOL
201
208
202 _user32.GetWindowThreadProcessId.argtypes = [_HANDLE, ctypes.c_void_p]
209 _user32.GetWindowThreadProcessId.argtypes = [_HANDLE, ctypes.c_void_p]
203 _user32.GetWindowThreadProcessId.restype = _DWORD
210 _user32.GetWindowThreadProcessId.restype = _DWORD
204
211
205 _user32.ShowWindow.argtypes = [_HANDLE, ctypes.c_int]
212 _user32.ShowWindow.argtypes = [_HANDLE, ctypes.c_int]
206 _user32.ShowWindow.restype = _BOOL
213 _user32.ShowWindow.restype = _BOOL
207
214
208 _WNDENUMPROC = ctypes.WINFUNCTYPE(_BOOL, _HWND, _LPARAM)
215 _WNDENUMPROC = ctypes.WINFUNCTYPE(_BOOL, _HWND, _LPARAM)
209 _user32.EnumWindows.argtypes = [_WNDENUMPROC, _LPARAM]
216 _user32.EnumWindows.argtypes = [_WNDENUMPROC, _LPARAM]
210 _user32.EnumWindows.restype = _BOOL
217 _user32.EnumWindows.restype = _BOOL
211
218
212 _kernel32.CreateToolhelp32Snapshot.argtypes = [_DWORD, _DWORD]
219 _kernel32.CreateToolhelp32Snapshot.argtypes = [_DWORD, _DWORD]
213 _kernel32.CreateToolhelp32Snapshot.restype = _BOOL
220 _kernel32.CreateToolhelp32Snapshot.restype = _BOOL
214
221
215 _kernel32.PeekNamedPipe.argtypes = [_HANDLE, ctypes.c_void_p, _DWORD,
222 _kernel32.PeekNamedPipe.argtypes = [_HANDLE, ctypes.c_void_p, _DWORD,
216 ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
223 ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
217 _kernel32.PeekNamedPipe.restype = _BOOL
224 _kernel32.PeekNamedPipe.restype = _BOOL
218
225
219 _kernel32.Process32First.argtypes = [_HANDLE, ctypes.c_void_p]
226 _kernel32.Process32First.argtypes = [_HANDLE, ctypes.c_void_p]
220 _kernel32.Process32First.restype = _BOOL
227 _kernel32.Process32First.restype = _BOOL
221
228
222 _kernel32.Process32Next.argtypes = [_HANDLE, ctypes.c_void_p]
229 _kernel32.Process32Next.argtypes = [_HANDLE, ctypes.c_void_p]
223 _kernel32.Process32Next.restype = _BOOL
230 _kernel32.Process32Next.restype = _BOOL
224
231
225 def _raiseoserror(name):
232 def _raiseoserror(name):
226 err = ctypes.WinError()
233 err = ctypes.WinError()
227 raise OSError(err.errno, '%s: %s' % (name, err.strerror))
234 raise OSError(err.errno, '%s: %s' % (name, err.strerror))
228
235
229 def _getfileinfo(name):
236 def _getfileinfo(name):
230 fh = _kernel32.CreateFileA(name, 0,
237 fh = _kernel32.CreateFileA(name, 0,
231 _FILE_SHARE_READ | _FILE_SHARE_WRITE | _FILE_SHARE_DELETE,
238 _FILE_SHARE_READ | _FILE_SHARE_WRITE | _FILE_SHARE_DELETE,
232 None, _OPEN_EXISTING, _FILE_FLAG_BACKUP_SEMANTICS, None)
239 None, _OPEN_EXISTING, _FILE_FLAG_BACKUP_SEMANTICS, None)
233 if fh == _INVALID_HANDLE_VALUE:
240 if fh == _INVALID_HANDLE_VALUE:
234 _raiseoserror(name)
241 _raiseoserror(name)
235 try:
242 try:
236 fi = _BY_HANDLE_FILE_INFORMATION()
243 fi = _BY_HANDLE_FILE_INFORMATION()
237 if not _kernel32.GetFileInformationByHandle(fh, ctypes.byref(fi)):
244 if not _kernel32.GetFileInformationByHandle(fh, ctypes.byref(fi)):
238 _raiseoserror(name)
245 _raiseoserror(name)
239 return fi
246 return fi
240 finally:
247 finally:
241 _kernel32.CloseHandle(fh)
248 _kernel32.CloseHandle(fh)
242
249
243 def oslink(src, dst):
250 def oslink(src, dst):
244 try:
251 try:
245 if not _kernel32.CreateHardLinkA(dst, src, None):
252 if not _kernel32.CreateHardLinkA(dst, src, None):
246 _raiseoserror(src)
253 _raiseoserror(src)
247 except AttributeError: # Wine doesn't support this function
254 except AttributeError: # Wine doesn't support this function
248 _raiseoserror(src)
255 _raiseoserror(src)
249
256
250 def nlinks(name):
257 def nlinks(name):
251 '''return number of hardlinks for the given file'''
258 '''return number of hardlinks for the given file'''
252 return _getfileinfo(name).nNumberOfLinks
259 return _getfileinfo(name).nNumberOfLinks
253
260
254 def samefile(path1, path2):
261 def samefile(path1, path2):
255 '''Returns whether path1 and path2 refer to the same file or directory.'''
262 '''Returns whether path1 and path2 refer to the same file or directory.'''
256 res1 = _getfileinfo(path1)
263 res1 = _getfileinfo(path1)
257 res2 = _getfileinfo(path2)
264 res2 = _getfileinfo(path2)
258 return (res1.dwVolumeSerialNumber == res2.dwVolumeSerialNumber
265 return (res1.dwVolumeSerialNumber == res2.dwVolumeSerialNumber
259 and res1.nFileIndexHigh == res2.nFileIndexHigh
266 and res1.nFileIndexHigh == res2.nFileIndexHigh
260 and res1.nFileIndexLow == res2.nFileIndexLow)
267 and res1.nFileIndexLow == res2.nFileIndexLow)
261
268
262 def samedevice(path1, path2):
269 def samedevice(path1, path2):
263 '''Returns whether path1 and path2 are on the same device.'''
270 '''Returns whether path1 and path2 are on the same device.'''
264 res1 = _getfileinfo(path1)
271 res1 = _getfileinfo(path1)
265 res2 = _getfileinfo(path2)
272 res2 = _getfileinfo(path2)
266 return res1.dwVolumeSerialNumber == res2.dwVolumeSerialNumber
273 return res1.dwVolumeSerialNumber == res2.dwVolumeSerialNumber
267
274
268 def peekpipe(pipe):
275 def peekpipe(pipe):
269 handle = msvcrt.get_osfhandle(pipe.fileno())
276 handle = msvcrt.get_osfhandle(pipe.fileno())
270 avail = _DWORD()
277 avail = _DWORD()
271
278
272 if not _kernel32.PeekNamedPipe(handle, None, 0, None, ctypes.byref(avail),
279 if not _kernel32.PeekNamedPipe(handle, None, 0, None, ctypes.byref(avail),
273 None):
280 None):
274 err = _kernel32.GetLastError()
281 err = _kernel32.GetLastError()
275 if err == _ERROR_BROKEN_PIPE:
282 if err == _ERROR_BROKEN_PIPE:
276 return 0
283 return 0
277 raise ctypes.WinError(err)
284 raise ctypes.WinError(err)
278
285
279 return avail.value
286 return avail.value
280
287
281 def testpid(pid):
288 def testpid(pid):
282 '''return True if pid is still running or unable to
289 '''return True if pid is still running or unable to
283 determine, False otherwise'''
290 determine, False otherwise'''
284 h = _kernel32.OpenProcess(_PROCESS_QUERY_INFORMATION, False, pid)
291 h = _kernel32.OpenProcess(_PROCESS_QUERY_INFORMATION, False, pid)
285 if h:
292 if h:
286 try:
293 try:
287 status = _DWORD()
294 status = _DWORD()
288 if _kernel32.GetExitCodeProcess(h, ctypes.byref(status)):
295 if _kernel32.GetExitCodeProcess(h, ctypes.byref(status)):
289 return status.value == _STILL_ACTIVE
296 return status.value == _STILL_ACTIVE
290 finally:
297 finally:
291 _kernel32.CloseHandle(h)
298 _kernel32.CloseHandle(h)
292 return _kernel32.GetLastError() != _ERROR_INVALID_PARAMETER
299 return _kernel32.GetLastError() != _ERROR_INVALID_PARAMETER
293
300
294 def executablepath():
301 def executablepath():
295 '''return full path of hg.exe'''
302 '''return full path of hg.exe'''
296 size = 600
303 size = 600
297 buf = ctypes.create_string_buffer(size + 1)
304 buf = ctypes.create_string_buffer(size + 1)
298 len = _kernel32.GetModuleFileNameA(None, ctypes.byref(buf), size)
305 len = _kernel32.GetModuleFileNameA(None, ctypes.byref(buf), size)
299 if len == 0:
306 if len == 0:
300 raise ctypes.WinError() # Note: WinError is a function
307 raise ctypes.WinError() # Note: WinError is a function
301 elif len == size:
308 elif len == size:
302 raise ctypes.WinError(_ERROR_INSUFFICIENT_BUFFER)
309 raise ctypes.WinError(_ERROR_INSUFFICIENT_BUFFER)
303 return buf.value
310 return buf.value
304
311
305 def getuser():
312 def getuser():
306 '''return name of current user'''
313 '''return name of current user'''
307 size = _DWORD(300)
314 size = _DWORD(300)
308 buf = ctypes.create_string_buffer(size.value + 1)
315 buf = ctypes.create_string_buffer(size.value + 1)
309 if not _advapi32.GetUserNameA(ctypes.byref(buf), ctypes.byref(size)):
316 if not _advapi32.GetUserNameA(ctypes.byref(buf), ctypes.byref(size)):
310 raise ctypes.WinError()
317 raise ctypes.WinError()
311 return buf.value
318 return buf.value
312
319
313 _signalhandler = []
320 _signalhandler = []
314
321
315 def setsignalhandler():
322 def setsignalhandler():
316 '''Register a termination handler for console events including
323 '''Register a termination handler for console events including
317 CTRL+C. python signal handlers do not work well with socket
324 CTRL+C. python signal handlers do not work well with socket
318 operations.
325 operations.
319 '''
326 '''
320 def handler(event):
327 def handler(event):
321 _kernel32.ExitProcess(1)
328 _kernel32.ExitProcess(1)
322
329
323 if _signalhandler:
330 if _signalhandler:
324 return # already registered
331 return # already registered
325 h = _SIGNAL_HANDLER(handler)
332 h = _SIGNAL_HANDLER(handler)
326 _signalhandler.append(h) # needed to prevent garbage collection
333 _signalhandler.append(h) # needed to prevent garbage collection
327 if not _kernel32.SetConsoleCtrlHandler(h, True):
334 if not _kernel32.SetConsoleCtrlHandler(h, True):
328 raise ctypes.WinError()
335 raise ctypes.WinError()
329
336
330 def hidewindow():
337 def hidewindow():
331
338
332 def callback(hwnd, pid):
339 def callback(hwnd, pid):
333 wpid = _DWORD()
340 wpid = _DWORD()
334 _user32.GetWindowThreadProcessId(hwnd, ctypes.byref(wpid))
341 _user32.GetWindowThreadProcessId(hwnd, ctypes.byref(wpid))
335 if pid == wpid.value:
342 if pid == wpid.value:
336 _user32.ShowWindow(hwnd, _SW_HIDE)
343 _user32.ShowWindow(hwnd, _SW_HIDE)
337 return False # stop enumerating windows
344 return False # stop enumerating windows
338 return True
345 return True
339
346
340 pid = _kernel32.GetCurrentProcessId()
347 pid = _kernel32.GetCurrentProcessId()
341 _user32.EnumWindows(_WNDENUMPROC(callback), pid)
348 _user32.EnumWindows(_WNDENUMPROC(callback), pid)
342
349
343 def termwidth():
350 def termwidth():
344 # cmd.exe does not handle CR like a unix console, the CR is
351 # cmd.exe does not handle CR like a unix console, the CR is
345 # counted in the line length. On 80 columns consoles, if 80
352 # counted in the line length. On 80 columns consoles, if 80
346 # characters are written, the following CR won't apply on the
353 # characters are written, the following CR won't apply on the
347 # current line but on the new one. Keep room for it.
354 # current line but on the new one. Keep room for it.
348 width = 79
355 width = 79
349 # Query stderr to avoid problems with redirections
356 # Query stderr to avoid problems with redirections
350 screenbuf = _kernel32.GetStdHandle(
357 screenbuf = _kernel32.GetStdHandle(
351 _STD_ERROR_HANDLE) # don't close the handle returned
358 _STD_ERROR_HANDLE) # don't close the handle returned
352 if screenbuf is None or screenbuf == _INVALID_HANDLE_VALUE:
359 if screenbuf is None or screenbuf == _INVALID_HANDLE_VALUE:
353 return width
360 return width
354 csbi = _CONSOLE_SCREEN_BUFFER_INFO()
361 csbi = _CONSOLE_SCREEN_BUFFER_INFO()
355 if not _kernel32.GetConsoleScreenBufferInfo(
362 if not _kernel32.GetConsoleScreenBufferInfo(
356 screenbuf, ctypes.byref(csbi)):
363 screenbuf, ctypes.byref(csbi)):
357 return width
364 return width
358 width = csbi.srWindow.Right - csbi.srWindow.Left
365 width = csbi.srWindow.Right - csbi.srWindow.Left
359 return width
366 return width
360
367
361 def _1stchild(pid):
368 def _1stchild(pid):
362 '''return the 1st found child of the given pid
369 '''return the 1st found child of the given pid
363
370
364 None is returned when no child is found'''
371 None is returned when no child is found'''
365 pe = _tagPROCESSENTRY32()
372 pe = _tagPROCESSENTRY32()
366
373
367 # create handle to list all processes
374 # create handle to list all processes
368 ph = _kernel32.CreateToolhelp32Snapshot(_TH32CS_SNAPPROCESS, 0)
375 ph = _kernel32.CreateToolhelp32Snapshot(_TH32CS_SNAPPROCESS, 0)
369 if ph == _INVALID_HANDLE_VALUE:
376 if ph == _INVALID_HANDLE_VALUE:
370 raise ctypes.WinError()
377 raise ctypes.WinError()
371 try:
378 try:
372 r = _kernel32.Process32First(ph, ctypes.byref(pe))
379 r = _kernel32.Process32First(ph, ctypes.byref(pe))
373 # loop over all processes
380 # loop over all processes
374 while r:
381 while r:
375 if pe.th32ParentProcessID == pid:
382 if pe.th32ParentProcessID == pid:
376 # return first child found
383 # return first child found
377 return pe.th32ProcessID
384 return pe.th32ProcessID
378 r = _kernel32.Process32Next(ph, ctypes.byref(pe))
385 r = _kernel32.Process32Next(ph, ctypes.byref(pe))
379 finally:
386 finally:
380 _kernel32.CloseHandle(ph)
387 _kernel32.CloseHandle(ph)
381 if _kernel32.GetLastError() != _ERROR_NO_MORE_FILES:
388 if _kernel32.GetLastError() != _ERROR_NO_MORE_FILES:
382 raise ctypes.WinError()
389 raise ctypes.WinError()
383 return None # no child found
390 return None # no child found
384
391
385 class _tochildpid(int): # pid is _DWORD, which always matches in an int
392 class _tochildpid(int): # pid is _DWORD, which always matches in an int
386 '''helper for spawndetached, returns the child pid on conversion to string
393 '''helper for spawndetached, returns the child pid on conversion to string
387
394
388 Does not resolve the child pid immediately because the child may not yet be
395 Does not resolve the child pid immediately because the child may not yet be
389 started.
396 started.
390 '''
397 '''
391 def childpid(self):
398 def childpid(self):
392 '''returns the child pid of the first found child of the process
399 '''returns the child pid of the first found child of the process
393 with this pid'''
400 with this pid'''
394 return _1stchild(self)
401 return _1stchild(self)
395 def __str__(self):
402 def __str__(self):
396 # run when the pid is written to the file
403 # run when the pid is written to the file
397 ppid = self.childpid()
404 ppid = self.childpid()
398 if ppid is None:
405 if ppid is None:
399 # race, child has exited since check
406 # race, child has exited since check
400 # fall back to this pid. Its process will also have disappeared,
407 # fall back to this pid. Its process will also have disappeared,
401 # raising the same error type later as when the child pid would
408 # raising the same error type later as when the child pid would
402 # be returned.
409 # be returned.
403 return " %d" % self
410 return " %d" % self
404 return str(ppid)
411 return str(ppid)
405
412
406 def spawndetached(args):
413 def spawndetached(args):
407 # No standard library function really spawns a fully detached
414 # No standard library function really spawns a fully detached
408 # process under win32 because they allocate pipes or other objects
415 # process under win32 because they allocate pipes or other objects
409 # to handle standard streams communications. Passing these objects
416 # to handle standard streams communications. Passing these objects
410 # to the child process requires handle inheritance to be enabled
417 # to the child process requires handle inheritance to be enabled
411 # which makes really detached processes impossible.
418 # which makes really detached processes impossible.
412 si = _STARTUPINFO()
419 si = _STARTUPINFO()
413 si.cb = ctypes.sizeof(_STARTUPINFO)
420 si.cb = ctypes.sizeof(_STARTUPINFO)
414
421
415 pi = _PROCESS_INFORMATION()
422 pi = _PROCESS_INFORMATION()
416
423
417 env = ''
424 env = ''
418 for k in os.environ:
425 for k in os.environ:
419 env += "%s=%s\0" % (k, os.environ[k])
426 env += "%s=%s\0" % (k, os.environ[k])
420 if not env:
427 if not env:
421 env = '\0'
428 env = '\0'
422 env += '\0'
429 env += '\0'
423
430
424 args = subprocess.list2cmdline(args)
431 args = subprocess.list2cmdline(args)
425 # Not running the command in shell mode makes Python 2.6 hang when
432 # Not running the command in shell mode makes Python 2.6 hang when
426 # writing to hgweb output socket.
433 # writing to hgweb output socket.
427 comspec = os.environ.get("COMSPEC", "cmd.exe")
434 comspec = os.environ.get("COMSPEC", "cmd.exe")
428 args = comspec + " /c " + args
435 args = comspec + " /c " + args
429
436
430 res = _kernel32.CreateProcessA(
437 res = _kernel32.CreateProcessA(
431 None, args, None, None, False, _CREATE_NO_WINDOW,
438 None, args, None, None, False, _CREATE_NO_WINDOW,
432 env, os.getcwd(), ctypes.byref(si), ctypes.byref(pi))
439 env, os.getcwd(), ctypes.byref(si), ctypes.byref(pi))
433 if not res:
440 if not res:
434 raise ctypes.WinError()
441 raise ctypes.WinError()
435
442
436 # _tochildpid because the process is the child of COMSPEC
443 # _tochildpid because the process is the child of COMSPEC
437 return _tochildpid(pi.dwProcessId)
444 return _tochildpid(pi.dwProcessId)
438
445
439 def unlink(f):
446 def unlink(f):
440 '''try to implement POSIX' unlink semantics on Windows'''
447 '''try to implement POSIX' unlink semantics on Windows'''
441
448
442 if os.path.isdir(f):
449 if os.path.isdir(f):
443 # use EPERM because it is POSIX prescribed value, even though
450 # use EPERM because it is POSIX prescribed value, even though
444 # unlink(2) on directories returns EISDIR on Linux
451 # unlink(2) on directories returns EISDIR on Linux
445 raise IOError(errno.EPERM,
452 raise IOError(errno.EPERM,
446 "Unlinking directory not permitted: '%s'" % f)
453 "Unlinking directory not permitted: '%s'" % f)
447
454
448 # POSIX allows to unlink and rename open files. Windows has serious
455 # POSIX allows to unlink and rename open files. Windows has serious
449 # problems with doing that:
456 # problems with doing that:
450 # - Calling os.unlink (or os.rename) on a file f fails if f or any
457 # - Calling os.unlink (or os.rename) on a file f fails if f or any
451 # hardlinked copy of f has been opened with Python's open(). There is no
458 # hardlinked copy of f has been opened with Python's open(). There is no
452 # way such a file can be deleted or renamed on Windows (other than
459 # way such a file can be deleted or renamed on Windows (other than
453 # scheduling the delete or rename for the next reboot).
460 # scheduling the delete or rename for the next reboot).
454 # - Calling os.unlink on a file that has been opened with Mercurial's
461 # - Calling os.unlink on a file that has been opened with Mercurial's
455 # posixfile (or comparable methods) will delay the actual deletion of
462 # posixfile (or comparable methods) will delay the actual deletion of
456 # the file for as long as the file is held open. The filename is blocked
463 # the file for as long as the file is held open. The filename is blocked
457 # during that time and cannot be used for recreating a new file under
464 # during that time and cannot be used for recreating a new file under
458 # that same name ("zombie file"). Directories containing such zombie files
465 # that same name ("zombie file"). Directories containing such zombie files
459 # cannot be removed or moved.
466 # cannot be removed or moved.
460 # A file that has been opened with posixfile can be renamed, so we rename
467 # A file that has been opened with posixfile can be renamed, so we rename
461 # f to a random temporary name before calling os.unlink on it. This allows
468 # f to a random temporary name before calling os.unlink on it. This allows
462 # callers to recreate f immediately while having other readers do their
469 # callers to recreate f immediately while having other readers do their
463 # implicit zombie filename blocking on a temporary name.
470 # implicit zombie filename blocking on a temporary name.
464
471
465 for tries in xrange(10):
472 for tries in xrange(10):
466 temp = '%s-%08x' % (f, random.randint(0, 0xffffffff))
473 temp = '%s-%08x' % (f, random.randint(0, 0xffffffff))
467 try:
474 try:
468 os.rename(f, temp) # raises OSError EEXIST if temp exists
475 os.rename(f, temp) # raises OSError EEXIST if temp exists
469 break
476 break
470 except OSError as e:
477 except OSError as e:
471 if e.errno != errno.EEXIST:
478 if e.errno != errno.EEXIST:
472 raise
479 raise
473 else:
480 else:
474 raise IOError(errno.EEXIST, "No usable temporary filename found")
481 raise IOError(errno.EEXIST, "No usable temporary filename found")
475
482
476 try:
483 try:
477 os.unlink(temp)
484 os.unlink(temp)
478 except OSError:
485 except OSError:
479 # The unlink might have failed because the READONLY attribute may heave
486 # The unlink might have failed because the READONLY attribute may heave
480 # been set on the original file. Rename works fine with READONLY set,
487 # been set on the original file. Rename works fine with READONLY set,
481 # but not os.unlink. Reset all attributes and try again.
488 # but not os.unlink. Reset all attributes and try again.
482 _kernel32.SetFileAttributesA(temp, _FILE_ATTRIBUTE_NORMAL)
489 _kernel32.SetFileAttributesA(temp, _FILE_ATTRIBUTE_NORMAL)
483 try:
490 try:
484 os.unlink(temp)
491 os.unlink(temp)
485 except OSError:
492 except OSError:
486 # The unlink might have failed due to some very rude AV-Scanners.
493 # The unlink might have failed due to some very rude AV-Scanners.
487 # Leaking a tempfile is the lesser evil than aborting here and
494 # Leaking a tempfile is the lesser evil than aborting here and
488 # leaving some potentially serious inconsistencies.
495 # leaving some potentially serious inconsistencies.
489 pass
496 pass
490
497
491 def makedir(path, notindexed):
498 def makedir(path, notindexed):
492 os.mkdir(path)
499 os.mkdir(path)
493 if notindexed:
500 if notindexed:
494 _kernel32.SetFileAttributesA(path, _FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)
501 _kernel32.SetFileAttributesA(path, _FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)
General Comments 0
You need to be logged in to leave comments. Login now