Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/win32.py @ 14345:bf9a105aed0a
win32.py: add argtypes and restype
This is a feature of ctypes. Without these, pypy complains with
RuntimeWarning: C function without declared arguments called
RuntimeWarning: C function without declared return type called
As a side effect of specifying restypes, the return value of e.g. CreateFileA
is now implicitly converted to an instance of _HANDLE, so we also need to
change the definition
_INVALID_HANDLE_VALUE = -1
to
_INVALID_HANDLE_VALUE = _HANDLE(-1).value
Otherwise, tests for equality to _INVALID_HANDLE_VALUE in code like
def _getfileinfo(name):
fh = _kernel32.CreateFileA(name, 0,
_FILE_SHARE_READ | _FILE_SHARE_WRITE | _FILE_SHARE_DELETE,
None, _OPEN_EXISTING, 0, None)
if fh == _INVALID_HANDLE_VALUE:
_raiseoserror(name)
would now fail to detect an invalid handle, which in turn would lead to
exceptions raised with wrong errno values, like e.g.
>>> nlinks('missing.txt')
Traceback (most recent call last):
...
OSError: [Errno 9] missing.txt: The handle is invalid.
instead of the correct (as per this patch and before it)
>>> nlinks('missing.txt')
Traceback (most recent call last):
...
OSError: [Errno 2] missing.txt: The system cannot find the file specified.
author | Adrian Buehlmann <adrian@cadifra.com> |
---|---|
date | Sun, 15 May 2011 21:33:51 +0200 |
parents | e1db8a00188b |
children | ec222a29bdf0 |
comparison
equal
deleted
inserted
replaced
14344:e1db8a00188b | 14345:bf9a105aed0a |
---|---|
7 | 7 |
8 import encoding | 8 import encoding |
9 import ctypes, errno, os, struct, subprocess, random | 9 import ctypes, errno, os, struct, subprocess, random |
10 | 10 |
11 _kernel32 = ctypes.windll.kernel32 | 11 _kernel32 = ctypes.windll.kernel32 |
12 _advapi32 = ctypes.windll.advapi32 | |
13 _user32 = ctypes.windll.user32 | |
12 | 14 |
13 _BOOL = ctypes.c_long | 15 _BOOL = ctypes.c_long |
14 _WORD = ctypes.c_ushort | 16 _WORD = ctypes.c_ushort |
15 _DWORD = ctypes.c_ulong | 17 _DWORD = ctypes.c_ulong |
18 _UINT = ctypes.c_uint | |
19 _LONG = ctypes.c_long | |
16 _LPCSTR = _LPSTR = ctypes.c_char_p | 20 _LPCSTR = _LPSTR = ctypes.c_char_p |
17 _HANDLE = ctypes.c_void_p | 21 _HANDLE = ctypes.c_void_p |
18 _HWND = _HANDLE | 22 _HWND = _HANDLE |
19 | 23 |
20 _INVALID_HANDLE_VALUE = -1 | 24 _INVALID_HANDLE_VALUE = _HANDLE(-1).value |
21 | 25 |
22 # GetLastError | 26 # GetLastError |
23 _ERROR_SUCCESS = 0 | 27 _ERROR_SUCCESS = 0 |
24 _ERROR_INVALID_PARAMETER = 87 | 28 _ERROR_INVALID_PARAMETER = 87 |
25 _ERROR_INSUFFICIENT_BUFFER = 122 | 29 _ERROR_INSUFFICIENT_BUFFER = 122 |
120 ('srWindow', _SMALL_RECT), | 124 ('srWindow', _SMALL_RECT), |
121 ('dwMaximumWindowSize', _COORD)] | 125 ('dwMaximumWindowSize', _COORD)] |
122 | 126 |
123 _STD_ERROR_HANDLE = _DWORD(-12).value | 127 _STD_ERROR_HANDLE = _DWORD(-12).value |
124 | 128 |
129 # types of parameters of C functions used (required by pypy) | |
130 | |
131 _kernel32.CreateFileA.argtypes = [_LPCSTR, _DWORD, _DWORD, ctypes.c_void_p, | |
132 _DWORD, _DWORD, _HANDLE] | |
133 _kernel32.CreateFileA.restype = _HANDLE | |
134 | |
135 _kernel32.GetFileInformationByHandle.argtypes = [_HANDLE, ctypes.c_void_p] | |
136 _kernel32.GetFileInformationByHandle.restype = _BOOL | |
137 | |
138 _kernel32.CloseHandle.argtypes = [_HANDLE] | |
139 _kernel32.CloseHandle.restype = _BOOL | |
140 | |
141 _kernel32.CreateHardLinkA.argtypes = [_LPCSTR, _LPCSTR, ctypes.c_void_p] | |
142 _kernel32.CreateHardLinkA.restype = _BOOL | |
143 | |
144 _kernel32.SetFileAttributesA.argtypes = [_LPCSTR, _DWORD] | |
145 _kernel32.SetFileAttributesA.restype = _BOOL | |
146 | |
147 _kernel32.OpenProcess.argtypes = [_DWORD, _BOOL, _DWORD] | |
148 _kernel32.OpenProcess.restype = _HANDLE | |
149 | |
150 _kernel32.GetExitCodeProcess.argtypes = [_HANDLE, ctypes.c_void_p] | |
151 _kernel32.GetExitCodeProcess.restype = _BOOL | |
152 | |
153 _kernel32.GetLastError.argtypes = [] | |
154 _kernel32.GetLastError.restype = _DWORD | |
155 | |
156 _kernel32.GetModuleFileNameA.argtypes = [_HANDLE, ctypes.c_void_p, _DWORD] | |
157 _kernel32.GetModuleFileNameA.restype = _DWORD | |
158 | |
159 _kernel32.CreateProcessA.argtypes = [_LPCSTR, _LPCSTR, ctypes.c_void_p, | |
160 ctypes.c_void_p, _BOOL, _DWORD, ctypes.c_void_p, _LPCSTR, ctypes.c_void_p, | |
161 ctypes.c_void_p] | |
162 _kernel32.CreateProcessA.restype = _BOOL | |
163 | |
164 _kernel32.ExitProcess.argtypes = [_UINT] | |
165 _kernel32.ExitProcess.restype = None | |
166 | |
167 _kernel32.GetCurrentProcessId.argtypes = [] | |
168 _kernel32.GetCurrentProcessId.restype = _DWORD | |
169 | |
170 _SIGNAL_HANDLER = ctypes.WINFUNCTYPE(_BOOL, _DWORD) | |
171 _kernel32.SetConsoleCtrlHandler.argtypes = [_SIGNAL_HANDLER, _BOOL] | |
172 _kernel32.SetConsoleCtrlHandler.restype = _BOOL | |
173 | |
174 _kernel32.GetStdHandle.argtypes = [_DWORD] | |
175 _kernel32.GetStdHandle.restype = _HANDLE | |
176 | |
177 _kernel32.GetConsoleScreenBufferInfo.argtypes = [_HANDLE, ctypes.c_void_p] | |
178 _kernel32.GetConsoleScreenBufferInfo.restype = _BOOL | |
179 | |
180 _advapi32.RegOpenKeyExA.argtypes = [_HANDLE, _LPCSTR, _DWORD, _DWORD, | |
181 ctypes.c_void_p] | |
182 _advapi32.RegOpenKeyExA.restype = _LONG | |
183 | |
184 _advapi32.RegQueryValueExA.argtypes = [_HANDLE, _LPCSTR, ctypes.c_void_p, | |
185 ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p] | |
186 _advapi32.RegQueryValueExA.restype = _LONG | |
187 | |
188 _advapi32.RegCloseKey.argtypes = [_HANDLE] | |
189 _advapi32.RegCloseKey.restype = _LONG | |
190 | |
191 _advapi32.GetUserNameA.argtypes = [ctypes.c_void_p, ctypes.c_void_p] | |
192 _advapi32.GetUserNameA.restype = _BOOL | |
193 | |
194 _user32.GetWindowThreadProcessId.argtypes = [_HANDLE, ctypes.c_void_p] | |
195 _user32.GetWindowThreadProcessId.restype = _DWORD | |
196 | |
197 _user32.ShowWindow.argtypes = [_HANDLE, ctypes.c_int] | |
198 _user32.ShowWindow.restype = _BOOL | |
199 | |
200 _WNDENUMPROC = ctypes.WINFUNCTYPE(_BOOL, _HWND, _LPARAM) | |
201 _user32.EnumWindows.argtypes = [_WNDENUMPROC, _LPARAM] | |
202 _user32.EnumWindows.restype = _BOOL | |
203 | |
125 def _raiseoserror(name): | 204 def _raiseoserror(name): |
126 err = ctypes.WinError() | 205 err = ctypes.WinError() |
127 raise OSError(err.errno, '%s: %s' % (name, err.strerror)) | 206 raise OSError(err.errno, '%s: %s' % (name, err.strerror)) |
128 | 207 |
129 def _getfileinfo(name): | 208 def _getfileinfo(name): |
187 is used. | 266 is used. |
188 scope: optionally specify scope for registry lookup, this can be | 267 scope: optionally specify scope for registry lookup, this can be |
189 a sequence of scopes to look up in order. Default (CURRENT_USER, | 268 a sequence of scopes to look up in order. Default (CURRENT_USER, |
190 LOCAL_MACHINE). | 269 LOCAL_MACHINE). |
191 ''' | 270 ''' |
192 adv = ctypes.windll.advapi32 | |
193 byref = ctypes.byref | 271 byref = ctypes.byref |
194 if scope is None: | 272 if scope is None: |
195 scope = (_HKEY_CURRENT_USER, _HKEY_LOCAL_MACHINE) | 273 scope = (_HKEY_CURRENT_USER, _HKEY_LOCAL_MACHINE) |
196 elif not isinstance(scope, (list, tuple)): | 274 elif not isinstance(scope, (list, tuple)): |
197 scope = (scope,) | 275 scope = (scope,) |
198 for s in scope: | 276 for s in scope: |
199 kh = _HANDLE() | 277 kh = _HANDLE() |
200 res = adv.RegOpenKeyExA(s, key, 0, _KEY_READ, ctypes.byref(kh)) | 278 res = _advapi32.RegOpenKeyExA(s, key, 0, _KEY_READ, ctypes.byref(kh)) |
201 if res != _ERROR_SUCCESS: | 279 if res != _ERROR_SUCCESS: |
202 continue | 280 continue |
203 try: | 281 try: |
204 size = _DWORD(600) | 282 size = _DWORD(600) |
205 type = _DWORD() | 283 type = _DWORD() |
206 buf = ctypes.create_string_buffer(size.value + 1) | 284 buf = ctypes.create_string_buffer(size.value + 1) |
207 res = adv.RegQueryValueExA(kh.value, valname, None, | 285 res = _advapi32.RegQueryValueExA(kh.value, valname, None, |
208 byref(type), buf, byref(size)) | 286 byref(type), buf, byref(size)) |
209 if res != _ERROR_SUCCESS: | 287 if res != _ERROR_SUCCESS: |
210 continue | 288 continue |
211 if type.value == _REG_SZ: | 289 if type.value == _REG_SZ: |
212 # never let a Unicode string escape into the wild | 290 # never let a Unicode string escape into the wild |
214 elif type.value == _REG_DWORD: | 292 elif type.value == _REG_DWORD: |
215 fmt = '<L' | 293 fmt = '<L' |
216 s = ctypes.string_at(byref(buf), struct.calcsize(fmt)) | 294 s = ctypes.string_at(byref(buf), struct.calcsize(fmt)) |
217 return struct.unpack(fmt, s)[0] | 295 return struct.unpack(fmt, s)[0] |
218 finally: | 296 finally: |
219 adv.RegCloseKey(kh.value) | 297 _advapi32.RegCloseKey(kh.value) |
220 | 298 |
221 def executablepath(): | 299 def executablepath(): |
222 '''return full path of hg.exe''' | 300 '''return full path of hg.exe''' |
223 size = 600 | 301 size = 600 |
224 buf = ctypes.create_string_buffer(size + 1) | 302 buf = ctypes.create_string_buffer(size + 1) |
229 raise ctypes.WinError(_ERROR_INSUFFICIENT_BUFFER) | 307 raise ctypes.WinError(_ERROR_INSUFFICIENT_BUFFER) |
230 return buf.value | 308 return buf.value |
231 | 309 |
232 def getuser(): | 310 def getuser(): |
233 '''return name of current user''' | 311 '''return name of current user''' |
234 adv = ctypes.windll.advapi32 | |
235 size = _DWORD(300) | 312 size = _DWORD(300) |
236 buf = ctypes.create_string_buffer(size.value + 1) | 313 buf = ctypes.create_string_buffer(size.value + 1) |
237 if not adv.GetUserNameA(ctypes.byref(buf), ctypes.byref(size)): | 314 if not _advapi32.GetUserNameA(ctypes.byref(buf), ctypes.byref(size)): |
238 raise ctypes.WinError() | 315 raise ctypes.WinError() |
239 return buf.value | 316 return buf.value |
240 | 317 |
241 _SIGNAL_HANDLER = ctypes.WINFUNCTYPE(_BOOL, _DWORD) | |
242 _signalhandler = [] | 318 _signalhandler = [] |
243 | 319 |
244 def setsignalhandler(): | 320 def setsignalhandler(): |
245 '''Register a termination handler for console events including | 321 '''Register a termination handler for console events including |
246 CTRL+C. python signal handlers do not work well with socket | 322 CTRL+C. python signal handlers do not work well with socket |
254 h = _SIGNAL_HANDLER(handler) | 330 h = _SIGNAL_HANDLER(handler) |
255 _signalhandler.append(h) # needed to prevent garbage collection | 331 _signalhandler.append(h) # needed to prevent garbage collection |
256 if not _kernel32.SetConsoleCtrlHandler(h, True): | 332 if not _kernel32.SetConsoleCtrlHandler(h, True): |
257 raise ctypes.WinError() | 333 raise ctypes.WinError() |
258 | 334 |
259 _WNDENUMPROC = ctypes.WINFUNCTYPE(_BOOL, _HWND, _LPARAM) | |
260 | |
261 def hidewindow(): | 335 def hidewindow(): |
262 user32 = ctypes.windll.user32 | |
263 | 336 |
264 def callback(hwnd, pid): | 337 def callback(hwnd, pid): |
265 wpid = _DWORD() | 338 wpid = _DWORD() |
266 user32.GetWindowThreadProcessId(hwnd, ctypes.byref(wpid)) | 339 _user32.GetWindowThreadProcessId(hwnd, ctypes.byref(wpid)) |
267 if pid == wpid.value: | 340 if pid == wpid.value: |
268 user32.ShowWindow(hwnd, _SW_HIDE) | 341 _user32.ShowWindow(hwnd, _SW_HIDE) |
269 return False # stop enumerating windows | 342 return False # stop enumerating windows |
270 return True | 343 return True |
271 | 344 |
272 pid = _kernel32.GetCurrentProcessId() | 345 pid = _kernel32.GetCurrentProcessId() |
273 user32.EnumWindows(_WNDENUMPROC(callback), pid) | 346 _user32.EnumWindows(_WNDENUMPROC(callback), pid) |
274 | 347 |
275 def termwidth(): | 348 def termwidth(): |
276 # cmd.exe does not handle CR like a unix console, the CR is | 349 # cmd.exe does not handle CR like a unix console, the CR is |
277 # counted in the line length. On 80 columns consoles, if 80 | 350 # counted in the line length. On 80 columns consoles, if 80 |
278 # characters are written, the following CR won't apply on the | 351 # characters are written, the following CR won't apply on the |