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