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