summaryrefslogtreecommitdiff
path: root/mercurial/win32.py
diff options
context:
space:
mode:
Diffstat (limited to 'mercurial/win32.py')
-rw-r--r--mercurial/win32.py95
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