Ejemplo n.º 1
0
def ErrCheckBool(result, func, args):
    """errcheck function for Windows functions that return a BOOL True
    on success"""
    if not result:
        raise WinError()
    return args
Ejemplo n.º 2
0
        def set_handle_inheritable(handle, inheritable):
            flags = HANDLE_FLAG_INHERIT if inheritable else 0

            ok = SetHandleInformation(handle, HANDLE_FLAG_INHERIT, flags)
            if not ok:
                raise WinError()
Ejemplo n.º 3
0
def err_on_zero_or_null_check(result, func, args):
    if not result:
        raise WinError()
    return args
Ejemplo n.º 4
0
            def _wait(self):
                # First, check to see if the process is still running
                if self._handle:
                    self.returncode = winprocess.GetExitCodeProcess(
                        self._handle)
                else:
                    # Dude, the process is like totally dead!
                    return self.returncode

                threadalive = False
                if hasattr(self, "_procmgrthread"):
                    threadalive = self._procmgrthread.is_alive()
                if self._job and threadalive and threading.current_thread(
                ) != self._procmgrthread:
                    self.debug("waiting with IO completion port")
                    # Then we are managing with IO Completion Ports
                    # wait on a signal so we know when we have seen the last
                    # process come through.
                    # We use queues to synchronize between the thread and this
                    # function because events just didn't have robust enough error
                    # handling on pre-2.7 versions
                    try:
                        # timeout is the max amount of time the procmgr thread will wait for
                        # child processes to shutdown before killing them with extreme prejudice.
                        item = self._process_events.get(
                            timeout=self.
                            MAX_IOCOMPLETION_PORT_NOTIFICATION_DELAY +
                            self.MAX_PROCESS_KILL_DELAY)
                        if item[self.pid] == 'FINISHED':
                            self.debug(
                                "received 'FINISHED' from _procmgrthread")
                            self._process_events.task_done()
                    except:
                        traceback.print_exc()
                        raise OSError(
                            "IO Completion Port failed to signal process shutdown"
                        )
                    finally:
                        if self._handle:
                            self.returncode = winprocess.GetExitCodeProcess(
                                self._handle)
                        self._cleanup()

                else:
                    # Not managing with job objects, so all we can reasonably do
                    # is call waitforsingleobject and hope for the best
                    self.debug("waiting without IO completion port")

                    if not self._ignore_children:
                        self.debug("NOT USING JOB OBJECTS!!!")
                    # First, make sure we have not already ended
                    if self.returncode != winprocess.STILL_ACTIVE:
                        self._cleanup()
                        return self.returncode

                    rc = None
                    if self._handle:
                        rc = winprocess.WaitForSingleObject(self._handle, -1)

                    if rc == winprocess.WAIT_TIMEOUT:
                        # The process isn't dead, so kill it
                        print("Timed out waiting for process to close, "
                              "attempting TerminateProcess")
                        self.kill()
                    elif rc == winprocess.WAIT_OBJECT_0:
                        # We caught WAIT_OBJECT_0, which indicates all is well
                        print("Single process terminated successfully")
                        self.returncode = winprocess.GetExitCodeProcess(
                            self._handle)
                    else:
                        # An error occured we should probably throw
                        rc = winprocess.GetLastError()
                        if rc:
                            raise WinError(rc)

                    self._cleanup()

                return self.returncode
 def setNoInherit(sock):
     """Mark the given socket fd as non-inheritable to child processes"""
     if not _SetHandleInformation(sock.fileno(), 1, 0):
         raise WinError()
Ejemplo n.º 6
0
def _errCheck(result, func, args):
    if result == 0:
        raise WinError()
    return args
Ejemplo n.º 7
0
# and kill the other children too).

SINK = object()

# get default args from subprocess.Popen to use in subproc.Popen
a = inspect.getargspec(subprocess.Popen.__init__)
_Popen_defaults = zip(a.args[-len(a.defaults):], a.defaults)
del a
if mswindows:
    # required for os.kill() to work
    _Popen_creationflags = subprocess.CREATE_NEW_PROCESS_GROUP

    if _kill_children_on_death:
        _chJob = win32job.CreateJobObject(None, "")
        if not _chJob:
            raise WinError()

        chJeli = win32job.QueryInformationJobObject(
            _chJob, win32job.JobObjectExtendedLimitInformation)
        # JOB_OBJECT_LIMIT_BREAKAWAY_OK allows children to assign grandchildren
        # to their own jobs
        chJeli['BasicLimitInformation']['LimitFlags'] |= (
            win32job.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
            | win32job.JOB_OBJECT_LIMIT_BREAKAWAY_OK)

        if win32job.SetInformationJobObject(
                _chJob, win32job.JobObjectExtendedLimitInformation,
                chJeli) == 0:
            raise WinError()
        del chJeli
Ejemplo n.º 8
0
 def read_memory(self, addr, size):
     buffer = create_string_buffer(size)
     if not self.kernel32.ReadProcessMemory(self.handle, c_long(addr), buffer, size, None):
         raise WinError()
     return buffer
Ejemplo n.º 9
0
    def _check(result, func, args):
        if result == error_value:
            raise WinError()

        return result
Ejemplo n.º 10
0
 def GetDiskFreeSpaceExErrCheck(result, unused_func, args):
     if not result:
         raise WinError()
     return args[1].value
Ejemplo n.º 11
0
def pdh_error_check(result, func, arguments):
    if result:
        raise WinError(result)
    return result
Ejemplo n.º 12
0
 def write(self, text):
     try:
         if self._hConsole is None:
             if isinstance(text, unicode):
                 text = text.encode('utf-8')
             self._stream.write(text)
         else:
             if not isinstance(text, unicode):
                 text = str(text).decode('utf-8')
             remaining = len(text)
             while remaining > 0:
                 n = DWORD(0)
                 # There is a shorter-than-documented limitation on the length of the string
                 # passed to WriteConsoleW (see #1232).
                 retval = WriteConsoleW(self._hConsole, text, min(remaining, 10000), byref(n), None)
                 if retval == 0:
                     raise IOError("WriteConsoleW failed with WinError: %s" % (WinError(get_last_error()),))
                 if n.value == 0:
                     raise IOError("WriteConsoleW returned %r, n.value = 0" % (retval,))
                 remaining -= n.value
                 if remaining == 0: break
                 text = text[n.value:]
     except Exception, e:
         _complain("%s.write: %r" % (self.name, e))
         raise
Ejemplo n.º 13
0
    # <https://msdn.microsoft.com/en-us/library/windows/desktop/ms683156%28v=vs.85%29.aspx>
    GetCommandLineW = WINFUNCTYPE(
        LPWSTR,
        use_last_error=True
    )(("GetCommandLineW", windll.kernel32))

    # <https://msdn.microsoft.com/en-us/library/windows/desktop/bb776391%28v=vs.85%29.aspx>
    CommandLineToArgvW = WINFUNCTYPE(
        POINTER(LPWSTR),  LPCWSTR, POINTER(c_int),
        use_last_error=True
    )(("CommandLineToArgvW", windll.shell32))

    argc = c_int(0)
    argv_unicode = CommandLineToArgvW(GetCommandLineW(), byref(argc))
    if argv_unicode is None:
        raise WinError(get_last_error())

    # Because of <http://bugs.python.org/issue8775> (and similar limitations in
    # twisted), the 'bin/tahoe' script cannot invoke us with the actual Unicode arguments.
    # Instead it "mangles" or escapes them using \x7F as an escape character, which we
    # unescape here.
    def unmangle(s):
        return re.sub(ur'\x7F[0-9a-fA-F]*\;', lambda m: unichr(int(m.group(0)[1:-1], 16)), s)

    try:
        argv = [unmangle(argv_unicode[i]).encode('utf-8') for i in xrange(0, argc.value)]
    except Exception, e:
        _complain("%s:  could not unmangle Unicode arguments.\n%r"
                  % (sys.argv[0], [argv_unicode[i] for i in xrange(0, argc.value)]))
        raise
Ejemplo n.º 14
0
    def terminate(self):
        """Terminates the timer.
		This should be called from the thread that initiated the timer.
		"""
        if not user32.KillTimer(self.hwnd, self.idEvent):
            raise WinError()
Ejemplo n.º 15
0
def _raise_winerror(code, error_desc):
    win_error_desc = FormatError(code).strip()
    error_desc = "%s: %s".format(error_desc, win_error_desc)
    raise WinError(code, error_desc)
Ejemplo n.º 16
0
 def free_remote(self, addr, size):
     if not self.kernel32.VirtualFreeEx(self.handle, addr, c_int(0), self.MEM_RELEASE):
         raise WinError()
Ejemplo n.º 17
0
def get_disk_stats(whichdir, reserved_space=0):
    """Return disk statistics for the storage disk, in the form of a dict
    with the following fields.
      total:            total bytes on disk
      free_for_root:    bytes actually free on disk
      free_for_nonroot: bytes free for "a non-privileged user" [Unix] or
                          the current user [Windows]; might take into
                          account quotas depending on platform
      used:             bytes used on disk
      avail:            bytes available excluding reserved space
    An AttributeError can occur if the OS has no API to get disk information.
    An EnvironmentError can occur if the OS call fails.

    whichdir is a directory on the filesystem in question -- the
    answer is about the filesystem, not about the directory, so the
    directory is used only to specify which filesystem.

    reserved_space is how many bytes to subtract from the answer, so
    you can pass how many bytes you would like to leave unused on this
    filesystem as reserved_space.
    """

    if have_GetDiskFreeSpaceExW:
        # If this is a Windows system and GetDiskFreeSpaceExW is available, use it.
        # (This might put up an error dialog unless
        # SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX) has been called,
        # which we do in allmydata.windows.fixups.initialize().)

        n_free_for_nonroot = c_ulonglong(0)
        n_total = c_ulonglong(0)
        n_free_for_root = c_ulonglong(0)
        retval = GetDiskFreeSpaceExW(whichdir, byref(n_free_for_nonroot),
                                     byref(n_total), byref(n_free_for_root))
        if retval == 0:
            raise OSError(
                "WinError: %s\n attempting to get disk statistics for %r" %
                (WinError(get_last_error()), whichdir))
        free_for_nonroot = n_free_for_nonroot.value
        total = n_total.value
        free_for_root = n_free_for_root.value
    else:
        # For Unix-like systems.
        # <http://docs.python.org/library/os.html#os.statvfs>
        # <http://opengroup.org/onlinepubs/7990989799/xsh/fstatvfs.html>
        # <http://opengroup.org/onlinepubs/7990989799/xsh/sysstatvfs.h.html>
        s = os.statvfs(whichdir)

        # on my mac laptop:
        #  statvfs(2) is a wrapper around statfs(2).
        #    statvfs.f_frsize = statfs.f_bsize :
        #     "minimum unit of allocation" (statvfs)
        #     "fundamental file system block size" (statfs)
        #    statvfs.f_bsize = statfs.f_iosize = stat.st_blocks : preferred IO size
        # on an encrypted home directory ("FileVault"), it gets f_blocks
        # wrong, and s.f_blocks*s.f_frsize is twice the size of my disk,
        # but s.f_bavail*s.f_frsize is correct

        total = s.f_frsize * s.f_blocks
        free_for_root = s.f_frsize * s.f_bfree
        free_for_nonroot = s.f_frsize * s.f_bavail

    # valid for all platforms:
    used = total - free_for_root
    avail = max(free_for_nonroot - reserved_space, 0)

    return {
        'total': total,
        'free_for_root': free_for_root,
        'free_for_nonroot': free_for_nonroot,
        'used': used,
        'avail': avail,
    }
Ejemplo n.º 18
0
 def write_memory(self, addr, string):
     size = len(string)
     if not self.kernel32.WriteProcessMemory(self.handle, addr, string, size, None):
         raise WinError()
Ejemplo n.º 19
0
 def __enter__(self):
     self.data_ptr = memory.GlobalLock(self.handle)
     if not self.data_ptr:
         del self.data_ptr
         raise WinError()
     return self
Ejemplo n.º 20
0
def ErrorIfZero(handle):
    if handle == 0:
        raise WinError()
    else:
        return handle
Ejemplo n.º 21
0
 def prevent_socket_inheritance(sock):
     """Mark the given socket fd as non-inheritable (Windows)."""
     if not windll.kernel32.SetHandleInformation(sock.fileno(), 1, 0):
         raise WinError()
Ejemplo n.º 22
0
    def _shutdown_with_windows_restart_manager(self, pid):
        """ Shut down a process using the Windows Restart Manager.

        When Windows shuts down, it uses a protocol including the
        WM_QUERYENDSESSION and WM_ENDSESSION messages to give
        applications a chance to shut down safely. The best way to
        simulate this is via the Restart Manager, which allows a process
        (such as an installer) to use the same mechanism to shut down
        any other processes which are using registered resources.

        This function starts a Restart Manager session, registers the
        process as a resource, and shuts down the process.

        :param pid: The process id (int) of the process to shutdown

        :raises: WindowsError: if a Windows API call fails
        """

        import ctypes
        from ctypes import Structure, POINTER, WINFUNCTYPE, windll, pointer, WinError
        from ctypes.wintypes import HANDLE, DWORD, BOOL, WCHAR, UINT, ULONG, LPCWSTR

        # set up Windows SDK types
        OpenProcess = windll.kernel32.OpenProcess
        OpenProcess.restype = HANDLE
        OpenProcess.argtypes = [
            DWORD,  # dwDesiredAccess
            BOOL,  # bInheritHandle
            DWORD
        ]  # dwProcessId
        PROCESS_QUERY_INFORMATION = 0x0400

        class FILETIME(Structure):
            _fields_ = [('dwLowDateTime', DWORD), ('dwHighDateTime', DWORD)]

        LPFILETIME = POINTER(FILETIME)

        GetProcessTimes = windll.kernel32.GetProcessTimes
        GetProcessTimes.restype = BOOL
        GetProcessTimes.argtypes = [
            HANDLE,  # hProcess
            LPFILETIME,  # lpCreationTime
            LPFILETIME,  # lpExitTime
            LPFILETIME,  # lpKernelTime
            LPFILETIME
        ]  # lpUserTime

        ERROR_SUCCESS = 0

        class RM_UNIQUE_PROCESS(Structure):
            _fields_ = [('dwProcessId', DWORD), ('ProcessStartTime', FILETIME)]

        RmStartSession = windll.rstrtmgr.RmStartSession
        RmStartSession.restype = DWORD
        RmStartSession.argtypes = [
            POINTER(DWORD),  # pSessionHandle
            DWORD,  # dwSessionFlags
            POINTER(WCHAR)
        ]  # strSessionKey

        class GUID(ctypes.Structure):
            _fields_ = [('Data1', ctypes.c_ulong), ('Data2', ctypes.c_ushort),
                        ('Data3', ctypes.c_ushort),
                        ('Data4', ctypes.c_ubyte * 8)]

        CCH_RM_SESSION_KEY = ctypes.sizeof(GUID) * 2

        RmRegisterResources = windll.rstrtmgr.RmRegisterResources
        RmRegisterResources.restype = DWORD
        RmRegisterResources.argtypes = [
            DWORD,  # dwSessionHandle
            UINT,  # nFiles
            POINTER(LPCWSTR),  # rgsFilenames
            UINT,  # nApplications
            POINTER(RM_UNIQUE_PROCESS),  # rgApplications
            UINT,  # nServices
            POINTER(LPCWSTR)
        ]  # rgsServiceNames

        RM_WRITE_STATUS_CALLBACK = WINFUNCTYPE(None, UINT)
        RmShutdown = windll.rstrtmgr.RmShutdown
        RmShutdown.restype = DWORD
        RmShutdown.argtypes = [
            DWORD,  # dwSessionHandle
            ULONG,  # lActionFlags
            RM_WRITE_STATUS_CALLBACK
        ]  # fnStatus

        RmEndSession = windll.rstrtmgr.RmEndSession
        RmEndSession.restype = DWORD
        RmEndSession.argtypes = [DWORD]  # dwSessionHandle

        # Get the info needed to uniquely identify the process
        hProc = OpenProcess(PROCESS_QUERY_INFORMATION, False, pid)
        if not hProc:
            raise WinError()

        creationTime = FILETIME()
        exitTime = FILETIME()
        kernelTime = FILETIME()
        userTime = FILETIME()
        if not GetProcessTimes(hProc, pointer(creationTime), pointer(exitTime),
                               pointer(kernelTime), pointer(userTime)):
            raise WinError()

        # Start the Restart Manager Session
        dwSessionHandle = DWORD()
        sessionKeyType = WCHAR * (CCH_RM_SESSION_KEY + 1)
        sessionKey = sessionKeyType()
        if RmStartSession(pointer(dwSessionHandle), 0,
                          sessionKey) != ERROR_SUCCESS:
            raise WinError()

        try:
            UProcs_count = 1
            UProcsArrayType = RM_UNIQUE_PROCESS * UProcs_count
            UProcs = UProcsArrayType(RM_UNIQUE_PROCESS(pid, creationTime))

            # Register the process as a resource
            if RmRegisterResources(dwSessionHandle, 0, None, UProcs_count,
                                   UProcs, 0, None) != ERROR_SUCCESS:
                raise WinError()

            # Shut down all processes using registered resources
            if RmShutdown(
                    dwSessionHandle, 0,
                    ctypes.cast(None,
                                RM_WRITE_STATUS_CALLBACK)) != ERROR_SUCCESS:
                raise WinError()

        finally:
            RmEndSession(dwSessionHandle)
Ejemplo n.º 23
0
def handle_err_check(result, func, args):
    if result == INVALID_HANDLE_VALUE:
        raise WinError(get_last_error())
    return result
Ejemplo n.º 24
0
            def _poll_iocompletion_port(self):
                # Watch the IO Completion port for status
                self._spawned_procs = {}
                countdowntokill = 0

                self.debug("start polling IO completion port")

                while True:
                    msgid = c_ulong(0)
                    compkey = c_ulong(0)
                    pid = c_ulong(0)
                    portstatus = winprocess.GetQueuedCompletionStatus(
                        self._io_port, byref(msgid), byref(compkey),
                        byref(pid), 5000)

                    # If the countdowntokill has been activated, we need to check
                    # if we should start killing the children or not.
                    if countdowntokill != 0:
                        diff = datetime.now() - countdowntokill
                        # Arbitrarily wait 3 minutes for windows to get its act together
                        # Windows sometimes takes a small nap between notifying the
                        # IO Completion port and actually killing the children, and we
                        # don't want to mistake that situation for the situation of an unexpected
                        # parent abort (which is what we're looking for here).
                        if diff.seconds > self.MAX_IOCOMPLETION_PORT_NOTIFICATION_DELAY:
                            print(
                                "WARNING | IO Completion Port failed to signal "
                                "process shutdown",
                                file=sys.stderr)
                            print(
                                "Parent process %s exited with children alive:"
                                % self.pid,
                                file=sys.stderr)
                            print("PIDS: %s" % ', '.join(
                                [str(i) for i in self._spawned_procs]),
                                  file=sys.stderr)
                            print(
                                "Attempting to kill them, but no guarantee of success",
                                file=sys.stderr)

                            self.kill()
                            self._process_events.put({self.pid: 'FINISHED'})
                            break

                    if not portstatus:
                        # Check to see what happened
                        errcode = winprocess.GetLastError()
                        if errcode == winprocess.ERROR_ABANDONED_WAIT_0:
                            # Then something has killed the port, break the loop
                            print("IO Completion Port unexpectedly closed",
                                  file=sys.stderr)
                            self._process_events.put({self.pid: 'FINISHED'})
                            break
                        elif errcode == winprocess.WAIT_TIMEOUT:
                            # Timeouts are expected, just keep on polling
                            continue
                        else:
                            print(
                                "Error Code %s trying to query IO Completion Port, "
                                "exiting" % errcode,
                                file=sys.stderr)
                            raise WinError(errcode)
                            break

                    if compkey.value == winprocess.COMPKEY_TERMINATE.value:
                        self.debug("compkeyterminate detected")
                        # Then we're done
                        break

                    # Check the status of the IO Port and do things based on it
                    if compkey.value == winprocess.COMPKEY_JOBOBJECT.value:
                        if msgid.value == winprocess.JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO:
                            # No processes left, time to shut down
                            # Signal anyone waiting on us that it is safe to shut down
                            self.debug("job object msg active processes zero")
                            self._process_events.put({self.pid: 'FINISHED'})
                            break
                        elif msgid.value == winprocess.JOB_OBJECT_MSG_NEW_PROCESS:
                            # New Process started
                            # Add the child proc to our list in case our parent flakes out on us
                            # without killing everything.
                            if pid.value != self.pid:
                                self._spawned_procs[pid.value] = 1
                                self.debug(
                                    "new process detected with pid value: %s" %
                                    pid.value)
                        elif msgid.value == winprocess.JOB_OBJECT_MSG_EXIT_PROCESS:
                            self.debug("process id %s exited normally" %
                                       pid.value)
                            # One process exited normally
                            if pid.value == self.pid and len(
                                    self._spawned_procs) > 0:
                                # Parent process dying, start countdown timer
                                countdowntokill = datetime.now()
                            elif pid.value in self._spawned_procs:
                                # Child Process died remove from list
                                del (self._spawned_procs[pid.value])
                        elif msgid.value == winprocess.JOB_OBJECT_MSG_ABNORMAL_EXIT_PROCESS:
                            # One process existed abnormally
                            self.debug("process id %s exited abnormally" %
                                       pid.value)
                            if pid.value == self.pid and len(
                                    self._spawned_procs) > 0:
                                # Parent process dying, start countdown timer
                                countdowntokill = datetime.now()
                            elif pid.value in self._spawned_procs:
                                # Child Process died remove from list
                                del self._spawned_procs[pid.value]
                        else:
                            # We don't care about anything else
                            self.debug("We got a message %s" % msgid.value)
                            pass
Ejemplo n.º 25
0
def bool_err_check(result, func, args):
    if not result:
        raise WinError(get_last_error())
    return result
Ejemplo n.º 26
0
def ErrCheckResumeThread(result, func, args):
    if result == -1:
        raise WinError()

    return args
Ejemplo n.º 27
0
 def load_from_pid(self, pid):
     self.unload()
     self.pid = c_ulong(pid)
     self.handle = self.kernel32.OpenProcess(self.PROC_ALL_ACCESS, 0, pid)
     if not self.handle:
         raise WinError()
Ejemplo n.º 28
0
def ErrCheckHandle(result, func, args):
    """errcheck function for Windows functions that return a HANDLE."""
    if not result:
        raise WinError()
    return AutoHANDLE(result)
Ejemplo n.º 29
0
 def unload(self):
     if self.handle:
         self.kernel32.CloseHandle(self.handle)
         if not self.handle:
             raise WinError()
     self.handle = None
Ejemplo n.º 30
0
def ZERO(i):
    if i != 0 and GetLastError() != 0:
        exc = WinError()
        exc.result = i
        raise exc
    return i
Ejemplo n.º 31
0
def PostMessage(hwnd, msg, wParam, lParam):
    if not user32.PostMessageW(hwnd, msg, wParam, lParam):
        raise WinError()