mercurial/win32.py
changeset 20425 ca6aa8362f33
parent 19159 1b329f8c7b24
child 20528 1a9ebc83a74c
equal deleted inserted replaced
20424:1da346bad3d8 20425:ca6aa8362f33
   117                 ('srWindow', _SMALL_RECT),
   117                 ('srWindow', _SMALL_RECT),
   118                 ('dwMaximumWindowSize', _COORD)]
   118                 ('dwMaximumWindowSize', _COORD)]
   119 
   119 
   120 _STD_ERROR_HANDLE = _DWORD(-12).value
   120 _STD_ERROR_HANDLE = _DWORD(-12).value
   121 
   121 
       
   122 # CreateToolhelp32Snapshot, Process32First, Process32Next
       
   123 _TH32CS_SNAPPROCESS = 0x00000002
       
   124 _MAX_PATH = 260
       
   125 
       
   126 class _tagPROCESSENTRY32(ctypes.Structure):
       
   127     _fields_ = [('dwsize', _DWORD),
       
   128                 ('cntUsage', _DWORD),
       
   129                 ('th32ProcessID', _DWORD),
       
   130                 ('th32DefaultHeapID', ctypes.c_void_p),
       
   131                 ('th32ModuleID', _DWORD),
       
   132                 ('cntThreads', _DWORD),
       
   133                 ('th32ParentProcessID', _DWORD),
       
   134                 ('pcPriClassBase', _LONG),
       
   135                 ('dwFlags', _DWORD),
       
   136                 ('szExeFile', ctypes.c_char * _MAX_PATH)]
       
   137 
       
   138     def __init__(self):
       
   139         super(_tagPROCESSENTRY32, self).__init__()
       
   140         self.dwsize = ctypes.sizeof(self)
       
   141 
       
   142 
   122 # types of parameters of C functions used (required by pypy)
   143 # types of parameters of C functions used (required by pypy)
   123 
   144 
   124 _kernel32.CreateFileA.argtypes = [_LPCSTR, _DWORD, _DWORD, ctypes.c_void_p,
   145 _kernel32.CreateFileA.argtypes = [_LPCSTR, _DWORD, _DWORD, ctypes.c_void_p,
   125     _DWORD, _DWORD, _HANDLE]
   146     _DWORD, _DWORD, _HANDLE]
   126 _kernel32.CreateFileA.restype = _HANDLE
   147 _kernel32.CreateFileA.restype = _HANDLE
   183 _user32.ShowWindow.restype = _BOOL
   204 _user32.ShowWindow.restype = _BOOL
   184 
   205 
   185 _WNDENUMPROC = ctypes.WINFUNCTYPE(_BOOL, _HWND, _LPARAM)
   206 _WNDENUMPROC = ctypes.WINFUNCTYPE(_BOOL, _HWND, _LPARAM)
   186 _user32.EnumWindows.argtypes = [_WNDENUMPROC, _LPARAM]
   207 _user32.EnumWindows.argtypes = [_WNDENUMPROC, _LPARAM]
   187 _user32.EnumWindows.restype = _BOOL
   208 _user32.EnumWindows.restype = _BOOL
       
   209 
       
   210 _kernel32.CreateToolhelp32Snapshot.argtypes = [_DWORD, _DWORD]
       
   211 _kernel32.CreateToolhelp32Snapshot.restype = _BOOL
       
   212 
       
   213 _kernel32.Process32First.argtypes = [_HANDLE, ctypes.c_void_p]
       
   214 _kernel32.Process32First.restype = _BOOL
       
   215 
       
   216 _kernel32.Process32Next.argtypes = [_HANDLE, ctypes.c_void_p]
       
   217 _kernel32.Process32Next.restype = _BOOL
   188 
   218 
   189 def _raiseoserror(name):
   219 def _raiseoserror(name):
   190     err = ctypes.WinError()
   220     err = ctypes.WinError()
   191     raise OSError(err.errno, '%s: %s' % (name, err.strerror))
   221     raise OSError(err.errno, '%s: %s' % (name, err.strerror))
   192 
   222 
   307                         screenbuf, ctypes.byref(csbi)):
   337                         screenbuf, ctypes.byref(csbi)):
   308         return width
   338         return width
   309     width = csbi.srWindow.Right - csbi.srWindow.Left
   339     width = csbi.srWindow.Right - csbi.srWindow.Left
   310     return width
   340     return width
   311 
   341 
       
   342 def _1stchild(pid):
       
   343     '''return the 1st found child of the given pid
       
   344 
       
   345     None is returned when no child is found'''
       
   346     pe = _tagPROCESSENTRY32()
       
   347 
       
   348     # create handle to list all processes
       
   349     ph = _kernel32.CreateToolhelp32Snapshot(_TH32CS_SNAPPROCESS, 0)
       
   350     if ph == _INVALID_HANDLE_VALUE:
       
   351         raise ctypes.WinError
       
   352     try:
       
   353         r = _kernel32.Process32First(ph, ctypes.byref(pe))
       
   354         # loop over all processes
       
   355         while r:
       
   356             if pe.th32ParentProcessID == pid:
       
   357                 # return first child found
       
   358                 return pe.th32ProcessID
       
   359             r = _kernel32.Process32Next(ph, ctypes.byref(pe))
       
   360     finally:
       
   361         _kernel32.CloseHandle(ph)
       
   362     if _kernel32.GetLastError() != _ERROR_NO_MORE_FILES:
       
   363         raise ctypes.WinError
       
   364     return None # no child found
       
   365 
       
   366 class _tochildpid(int): # pid is _DWORD, which always matches in an int
       
   367     '''helper for spawndetached, returns the child pid on conversion to string
       
   368 
       
   369     Does not resolve the child pid immediately because the child may not yet be
       
   370     started.
       
   371     '''
       
   372     def childpid(self):
       
   373         '''returns the child pid of the first found child of the process
       
   374         with this pid'''
       
   375         return _1stchild(self)
       
   376     def __str__(self):
       
   377         # run when the pid is written to the file
       
   378         ppid = self.childpid()
       
   379         if ppid is None:
       
   380             # race, child has exited since check
       
   381             # fall back to this pid. Its process will also have disappeared,
       
   382             # raising the same error type later as when the child pid would
       
   383             # be returned.
       
   384             return " %d" % self
       
   385         return str(ppid)
       
   386 
   312 def spawndetached(args):
   387 def spawndetached(args):
   313     # No standard library function really spawns a fully detached
   388     # No standard library function really spawns a fully detached
   314     # process under win32 because they allocate pipes or other objects
   389     # process under win32 because they allocate pipes or other objects
   315     # to handle standard streams communications. Passing these objects
   390     # to handle standard streams communications. Passing these objects
   316     # to the child process requires handle inheritance to be enabled
   391     # to the child process requires handle inheritance to be enabled
   337         None, args, None, None, False, _CREATE_NO_WINDOW,
   412         None, args, None, None, False, _CREATE_NO_WINDOW,
   338         env, os.getcwd(), ctypes.byref(si), ctypes.byref(pi))
   413         env, os.getcwd(), ctypes.byref(si), ctypes.byref(pi))
   339     if not res:
   414     if not res:
   340         raise ctypes.WinError
   415         raise ctypes.WinError
   341 
   416 
   342     return pi.dwProcessId
   417     # _tochildpid because the process is the child of COMSPEC
       
   418     return _tochildpid(pi.dwProcessId)
   343 
   419 
   344 def unlink(f):
   420 def unlink(f):
   345     '''try to implement POSIX' unlink semantics on Windows'''
   421     '''try to implement POSIX' unlink semantics on Windows'''
   346 
   422 
   347     if os.path.isdir(f):
   423     if os.path.isdir(f):