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, struct, subprocess, random |
8 import encoding |
|
9 import ctypes, errno, os, subprocess, random, _winreg |
9 |
10 |
10 _kernel32 = ctypes.windll.kernel32 |
11 _kernel32 = ctypes.windll.kernel32 |
11 _advapi32 = ctypes.windll.advapi32 |
12 _advapi32 = ctypes.windll.advapi32 |
12 _user32 = ctypes.windll.user32 |
13 _user32 = ctypes.windll.user32 |
13 |
14 |
66 # Process Security and Access Rights |
67 # Process Security and Access Rights |
67 _PROCESS_QUERY_INFORMATION = 0x0400 |
68 _PROCESS_QUERY_INFORMATION = 0x0400 |
68 |
69 |
69 # GetExitCodeProcess |
70 # GetExitCodeProcess |
70 _STILL_ACTIVE = 259 |
71 _STILL_ACTIVE = 259 |
71 |
|
72 # registry |
|
73 _HKEY_CURRENT_USER = 0x80000001L |
|
74 _HKEY_LOCAL_MACHINE = 0x80000002L |
|
75 _KEY_READ = 0x20019 |
|
76 _REG_SZ = 1 |
|
77 _REG_DWORD = 4 |
|
78 |
72 |
79 class _STARTUPINFO(ctypes.Structure): |
73 class _STARTUPINFO(ctypes.Structure): |
80 _fields_ = [('cb', _DWORD), |
74 _fields_ = [('cb', _DWORD), |
81 ('lpReserved', _LPSTR), |
75 ('lpReserved', _LPSTR), |
82 ('lpDesktop', _LPSTR), |
76 ('lpDesktop', _LPSTR), |
177 _kernel32.GetStdHandle.restype = _HANDLE |
171 _kernel32.GetStdHandle.restype = _HANDLE |
178 |
172 |
179 _kernel32.GetConsoleScreenBufferInfo.argtypes = [_HANDLE, ctypes.c_void_p] |
173 _kernel32.GetConsoleScreenBufferInfo.argtypes = [_HANDLE, ctypes.c_void_p] |
180 _kernel32.GetConsoleScreenBufferInfo.restype = _BOOL |
174 _kernel32.GetConsoleScreenBufferInfo.restype = _BOOL |
181 |
175 |
182 _advapi32.RegOpenKeyExA.argtypes = [_HANDLE, _LPCSTR, _DWORD, _DWORD, |
|
183 ctypes.c_void_p] |
|
184 _advapi32.RegOpenKeyExA.restype = _LONG |
|
185 |
|
186 _advapi32.RegQueryValueExA.argtypes = [_HANDLE, _LPCSTR, ctypes.c_void_p, |
|
187 ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p] |
|
188 _advapi32.RegQueryValueExA.restype = _LONG |
|
189 |
|
190 _advapi32.RegCloseKey.argtypes = [_HANDLE] |
|
191 _advapi32.RegCloseKey.restype = _LONG |
|
192 |
|
193 _advapi32.GetUserNameA.argtypes = [ctypes.c_void_p, ctypes.c_void_p] |
176 _advapi32.GetUserNameA.argtypes = [ctypes.c_void_p, ctypes.c_void_p] |
194 _advapi32.GetUserNameA.restype = _BOOL |
177 _advapi32.GetUserNameA.restype = _BOOL |
195 |
178 |
196 _user32.GetWindowThreadProcessId.argtypes = [_HANDLE, ctypes.c_void_p] |
179 _user32.GetWindowThreadProcessId.argtypes = [_HANDLE, ctypes.c_void_p] |
197 _user32.GetWindowThreadProcessId.restype = _DWORD |
180 _user32.GetWindowThreadProcessId.restype = _DWORD |
268 is used. |
251 is used. |
269 scope: optionally specify scope for registry lookup, this can be |
252 scope: optionally specify scope for registry lookup, this can be |
270 a sequence of scopes to look up in order. Default (CURRENT_USER, |
253 a sequence of scopes to look up in order. Default (CURRENT_USER, |
271 LOCAL_MACHINE). |
254 LOCAL_MACHINE). |
272 ''' |
255 ''' |
273 byref = ctypes.byref |
|
274 if scope is None: |
256 if scope is None: |
275 scope = (_HKEY_CURRENT_USER, _HKEY_LOCAL_MACHINE) |
257 scope = (_winreg.HKEY_CURRENT_USER, _winreg.HKEY_LOCAL_MACHINE) |
276 elif not isinstance(scope, (list, tuple)): |
258 elif not isinstance(scope, (list, tuple)): |
277 scope = (scope,) |
259 scope = (scope,) |
278 for s in scope: |
260 for s in scope: |
279 kh = _HANDLE() |
|
280 res = _advapi32.RegOpenKeyExA(s, key, 0, _KEY_READ, ctypes.byref(kh)) |
|
281 if res != _ERROR_SUCCESS: |
|
282 continue |
|
283 try: |
261 try: |
284 size = _DWORD(600) |
262 val = _winreg.QueryValueEx(_winreg.OpenKey(s, key), valname)[0] |
285 type = _DWORD() |
263 # never let a Unicode string escape into the wild |
286 buf = ctypes.create_string_buffer(size.value + 1) |
264 return encoding.tolocal(val.encode('UTF-8')) |
287 res = _advapi32.RegQueryValueExA(kh.value, valname, None, |
265 except EnvironmentError: |
288 byref(type), buf, byref(size)) |
266 pass |
289 if res != _ERROR_SUCCESS: |
|
290 continue |
|
291 if type.value == _REG_SZ: |
|
292 # string is in ANSI code page, aka local encoding |
|
293 return buf.value |
|
294 elif type.value == _REG_DWORD: |
|
295 fmt = '<L' |
|
296 s = ctypes.string_at(byref(buf), struct.calcsize(fmt)) |
|
297 return struct.unpack(fmt, s)[0] |
|
298 finally: |
|
299 _advapi32.RegCloseKey(kh.value) |
|
300 |
267 |
301 def executablepath(): |
268 def executablepath(): |
302 '''return full path of hg.exe''' |
269 '''return full path of hg.exe''' |
303 size = 600 |
270 size = 600 |
304 buf = ctypes.create_string_buffer(size + 1) |
271 buf = ctypes.create_string_buffer(size + 1) |