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