diff options
Diffstat (limited to 'mercurial/win32.py')
-rw-r--r-- | mercurial/win32.py | 95 |
1 files changed, 77 insertions, 18 deletions
diff --git a/mercurial/win32.py b/mercurial/win32.py index 6b3650f..e886caf 100644 --- a/mercurial/win32.py +++ b/mercurial/win32.py @@ -5,7 +5,8 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -import ctypes, errno, os, subprocess, random +import encoding +import ctypes, errno, os, struct, subprocess, random _kernel32 = ctypes.windll.kernel32 _advapi32 = ctypes.windll.advapi32 @@ -59,8 +60,6 @@ _FILE_SHARE_DELETE = 0x00000004 _OPEN_EXISTING = 3 -_FILE_FLAG_BACKUP_SEMANTICS = 0x02000000 - # SetFileAttributes _FILE_ATTRIBUTE_NORMAL = 0x80 _FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x2000 @@ -71,6 +70,13 @@ _PROCESS_QUERY_INFORMATION = 0x0400 # GetExitCodeProcess _STILL_ACTIVE = 259 +# registry +_HKEY_CURRENT_USER = 0x80000001L +_HKEY_LOCAL_MACHINE = 0x80000002L +_KEY_READ = 0x20019 +_REG_SZ = 1 +_REG_DWORD = 4 + class _STARTUPINFO(ctypes.Structure): _fields_ = [('cb', _DWORD), ('lpReserved', _LPSTR), @@ -97,7 +103,8 @@ class _PROCESS_INFORMATION(ctypes.Structure): ('dwProcessId', _DWORD), ('dwThreadId', _DWORD)] -_CREATE_NO_WINDOW = 0x08000000 +_DETACHED_PROCESS = 0x00000008 +_STARTF_USESHOWWINDOW = 0x00000001 _SW_HIDE = 0 class _COORD(ctypes.Structure): @@ -173,6 +180,17 @@ _kernel32.GetStdHandle.restype = _HANDLE _kernel32.GetConsoleScreenBufferInfo.argtypes = [_HANDLE, ctypes.c_void_p] _kernel32.GetConsoleScreenBufferInfo.restype = _BOOL +_advapi32.RegOpenKeyExA.argtypes = [_HANDLE, _LPCSTR, _DWORD, _DWORD, + ctypes.c_void_p] +_advapi32.RegOpenKeyExA.restype = _LONG + +_advapi32.RegQueryValueExA.argtypes = [_HANDLE, _LPCSTR, ctypes.c_void_p, + ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p] +_advapi32.RegQueryValueExA.restype = _LONG + +_advapi32.RegCloseKey.argtypes = [_HANDLE] +_advapi32.RegCloseKey.restype = _LONG + _advapi32.GetUserNameA.argtypes = [ctypes.c_void_p, ctypes.c_void_p] _advapi32.GetUserNameA.restype = _BOOL @@ -193,7 +211,7 @@ def _raiseoserror(name): def _getfileinfo(name): fh = _kernel32.CreateFileA(name, 0, _FILE_SHARE_READ | _FILE_SHARE_WRITE | _FILE_SHARE_DELETE, - None, _OPEN_EXISTING, _FILE_FLAG_BACKUP_SEMANTICS, None) + None, _OPEN_EXISTING, 0, None) if fh == _INVALID_HANDLE_VALUE: _raiseoserror(name) try: @@ -215,18 +233,20 @@ def nlinks(name): '''return number of hardlinks for the given file''' return _getfileinfo(name).nNumberOfLinks -def samefile(path1, path2): - '''Returns whether path1 and path2 refer to the same file or directory.''' - res1 = _getfileinfo(path1) - res2 = _getfileinfo(path2) +def samefile(fpath1, fpath2): + '''Returns whether fpath1 and fpath2 refer to the same file. This is only + guaranteed to work for files, not directories.''' + res1 = _getfileinfo(fpath1) + res2 = _getfileinfo(fpath2) return (res1.dwVolumeSerialNumber == res2.dwVolumeSerialNumber and res1.nFileIndexHigh == res2.nFileIndexHigh and res1.nFileIndexLow == res2.nFileIndexLow) -def samedevice(path1, path2): - '''Returns whether path1 and path2 are on the same device.''' - res1 = _getfileinfo(path1) - res2 = _getfileinfo(path2) +def samedevice(fpath1, fpath2): + '''Returns whether fpath1 and fpath2 are on the same device. This is only + guaranteed to work for files, not directories.''' + res1 = _getfileinfo(fpath1) + res2 = _getfileinfo(fpath2) return res1.dwVolumeSerialNumber == res2.dwVolumeSerialNumber def testpid(pid): @@ -242,13 +262,50 @@ def testpid(pid): _kernel32.CloseHandle(h) return _kernel32.GetLastError() != _ERROR_INVALID_PARAMETER +def lookupreg(key, valname=None, scope=None): + ''' Look up a key/value name in the Windows registry. + + valname: value name. If unspecified, the default value for the key + is used. + scope: optionally specify scope for registry lookup, this can be + a sequence of scopes to look up in order. Default (CURRENT_USER, + LOCAL_MACHINE). + ''' + byref = ctypes.byref + if scope is None: + scope = (_HKEY_CURRENT_USER, _HKEY_LOCAL_MACHINE) + elif not isinstance(scope, (list, tuple)): + scope = (scope,) + for s in scope: + kh = _HANDLE() + res = _advapi32.RegOpenKeyExA(s, key, 0, _KEY_READ, ctypes.byref(kh)) + if res != _ERROR_SUCCESS: + continue + try: + size = _DWORD(600) + type = _DWORD() + buf = ctypes.create_string_buffer(size.value + 1) + res = _advapi32.RegQueryValueExA(kh.value, valname, None, + byref(type), buf, byref(size)) + if res != _ERROR_SUCCESS: + continue + if type.value == _REG_SZ: + # never let a Unicode string escape into the wild + return encoding.tolocal(buf.value.encode('UTF-8')) + elif type.value == _REG_DWORD: + fmt = '<L' + s = ctypes.string_at(byref(buf), struct.calcsize(fmt)) + return struct.unpack(fmt, s)[0] + finally: + _advapi32.RegCloseKey(kh.value) + def executablepath(): '''return full path of hg.exe''' size = 600 buf = ctypes.create_string_buffer(size + 1) len = _kernel32.GetModuleFileNameA(None, ctypes.byref(buf), size) if len == 0: - raise ctypes.WinError + raise ctypes.WinError() elif len == size: raise ctypes.WinError(_ERROR_INSUFFICIENT_BUFFER) return buf.value @@ -258,7 +315,7 @@ def getuser(): size = _DWORD(300) buf = ctypes.create_string_buffer(size.value + 1) if not _advapi32.GetUserNameA(ctypes.byref(buf), ctypes.byref(size)): - raise ctypes.WinError + raise ctypes.WinError() return buf.value _signalhandler = [] @@ -276,7 +333,7 @@ def setsignalhandler(): h = _SIGNAL_HANDLER(handler) _signalhandler.append(h) # needed to prevent garbage collection if not _kernel32.SetConsoleCtrlHandler(h, True): - raise ctypes.WinError + raise ctypes.WinError() def hidewindow(): @@ -317,6 +374,8 @@ def spawndetached(args): # which makes really detached processes impossible. si = _STARTUPINFO() si.cb = ctypes.sizeof(_STARTUPINFO) + si.dwFlags = _STARTF_USESHOWWINDOW + si.wShowWindow = _SW_HIDE pi = _PROCESS_INFORMATION() @@ -334,10 +393,10 @@ def spawndetached(args): args = comspec + " /c " + args res = _kernel32.CreateProcessA( - None, args, None, None, False, _CREATE_NO_WINDOW, + None, args, None, None, False, _DETACHED_PROCESS, env, os.getcwd(), ctypes.byref(si), ctypes.byref(pi)) if not res: - raise ctypes.WinError + raise ctypes.WinError() return pi.dwProcessId |