Example #1
0
def process__get_executable_filename(thread_pid):
    psapi = WinDLL('psapi.dll')
    EnumProcesses = psapi.EnumProcesses
    EnumProcessModules = psapi.EnumProcessModules
    GetModuleBaseName = psapi.GetModuleBaseNameW
    # Alternate: GetModuleFileNameEx
    GetProcessImageFileName = psapi.GetProcessImageFileNameW

    hproc = windll.kernel32.OpenProcess(
        PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, False, thread_pid)
    try:
        filename = create_unicode_buffer(MAX_FILENAME_LENGTH + 1)

        res = GetProcessImageFileName(hproc, None, byref(filename),
                                      MAX_FILENAME_LENGTH + 1)
        if res > 0:
            return filename.value[:res]
    finally:
        windll.kernel32.CloseHandle(hproc)

    # So, GetProcessImageFileName failed, as it's apt to do.
    # So, do this the hard way.

    process_list = (wintypes.DWORD * MAX_PROCESS_COUNT)()
    bytes_returned = wintypes.DWORD()
    res = EnumProcesses(process_list, c_sizeof(process_list),
                        byref(bytes_returned))
    if res != 0:
        return None
        # raise ctypes.WinError()
    for i in range(bytes_returned / c_sizeof(wintypes.DWORD)):
        pid = process_list[i]
        if pid == thread_pid:
            hproc = windll.kernel32.OpenProcess(
                PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, None, pid)
            if hproc is None or 0 == hproc:
                continue
            try:
                buffer_index_count = 1024
                count_allocated_space = wintypes.DWORD()
                hmod_list = (wintypes.HMODULE * buffer_index_count)()
                res = EnumProcessModules(hproc.value, hmod_list,
                                         wintypes.DWORD(c_sizeof(hmod_list)),
                                         byref(count_allocated_space))
                if res == 0:
                    # Error; ignore
                    continue
                for j in range(count_allocated_space /
                               c_sizeof(wintypes.HMODULE)):
                    mod_name = create_unicode_buffer(MAX_FILENAME_LENGTH + 1)
                    res = GetModuleBaseName(hproc, hmod_list[j], mod_name,
                                            MAX_FILENAME_LENGTH + 1)
                    if res != 0:
                        return str(mod_name.value[:res])
            finally:
                windll.kernel32.CloseHandle(hproc)
    return None
Example #2
0
def shell__set_window_metrics(metrics):
    SystemParametersInfoW = windll.user32.SystemParametersInfoW

    # Always restore the original user metrics at exit time.
    root_metrics = None
    if _BASE_OS_METRICS[0] is None:
        root_metrics = shell__get_raw_window_metrics()
        _BASE_OS_METRICS[0] = root_metrics
        atexit.register(shell__set_window_metrics, root_metrics)

    if isinstance(metrics, dict):
        m = root_metrics or shell__get_raw_window_metrics()
        m.cbSize = c_sizeof(NONCLIENTMETRICS)
        if 'border-width' in metrics:
            m.iBorderWidth = metrics['border-width']
        if 'scroll-width' in metrics:
            m.iScrollWidth = metrics['scroll-width']
        if 'scroll-height' in metrics:
            m.iScrollHeight = metrics['scroll-height']
        if 'caption-width' in metrics:
            m.iCaptionWidth = metrics['caption-width']
        if 'caption-height' in metrics:
            m.iCaptionHeight = metrics['caption-height']
        if 'caption-font' in metrics:
            m.lfCaptionFont = _dict_to_font(metrics['caption-font'],
                                            m.lfCaptionFont)
        if 'sm-caption-width' in metrics:
            m.iSmCaptionWidth = metrics['sm-caption-width']
        if 'sm-caption-height' in metrics:
            m.iSmCaptionHeight = metrics['sm-caption-height']
        if 'sm-caption-font' in metrics:
            m.lfSmCaptionFont = _dict_to_font(metrics['sm-caption-font'],
                                              m.lfSmCaptionFont)
        if 'menu-width' in metrics:
            m.iMenuWidth = metrics['menu-width']
        if 'menu-height' in metrics:
            m.iMenuHeight = metrics['menu-height']
        if 'menu-font' in metrics:
            m.lfMenuFont = _dict_to_font(metrics[''], m.lfMenuFont)
        if 'status-font' in metrics:
            m.lfStatusFont = _dict_to_font(metrics['status-font'],
                                           m.lfStatusFont)
        if 'message-font' in metrics:
            m.lfMessageFont = _dict_to_font(metrics['message-font'],
                                            m.lfMessageFont)
        metrics = m

    assert isinstance(metrics, NONCLIENTMETRICS)
    metrics.cbSize = c_sizeof(NONCLIENTMETRICS)
    # TODO change 0 to SPIF_SENDCHANGE
    res = SystemParametersInfoW(SPI_SETNONCLIENTMETRICS, metrics.cbSize,
                                byref(metrics), 0)
    if res != 0:
        raise WinError()
Example #3
0
def process__get_all_pids():
    process_buff = (wintypes.DWORD * 2048)()
    process_size = wintypes.DWORD()
    res = windll.psapi.EnumProcesses(process_buff, c_sizeof(process_buff),
                                     byref(process_size))
    if res != 0:
        raise WinError()
    count = process_size / c_sizeof(wintypes.DWORD)
    ret = []
    for i in range(count):
        ret.append(process_buff[i])
    return ret
Example #4
0
def _bind(s, addr):
    sa_addr = sockaddr_in()
    host, port = addr
    sa_addr.sin_family = socket.AF_INET
    sa_addr.sin_port = socket.htons(port)
    sa_addr.sin_addr.S_addr = unpack('<i', socket.inet_aton(host))[0]

    low_bind(s, byref(sa_addr), c_sizeof(sa_addr))
Example #5
0
def _getsockname(s):
    sa_addr = sockaddr_in()
    sa_addr_len = c_int(c_sizeof(sa_addr))
    low_getsockname(s, byref(sa_addr), byref(sa_addr_len))

    port = socket.ntohs(sa_addr.sin_port)
    host = socket.inet_ntoa(pack('<i', sa_addr.sin_addr.S_addr))
    addr = (host, port)
    return addr
Example #6
0
def WSAAccept(s):
    sa_addr = sockaddr_in()
    sa_addr_len = c_int(c_sizeof(sa_addr))
    rc = lowWSAAccept(s, byref(sa_addr), byref(sa_addr_len), None, None)

    port = socket.ntohs(sa_addr.sin_port)
    host = socket.inet_ntoa(pack('<i', sa_addr.sin_addr.S_addr))
    addr = (host, port)
    return (rc, addr)
Example #7
0
def shell__get_raw_window_metrics():
    SystemParametersInfoW = windll.user32.SystemParametersInfoW
    metrics = NONCLIENTMETRICS()
    metrics.cbSize = c_sizeof(NONCLIENTMETRICS)
    res = SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, metrics.cbSize,
                                byref(metrics), 0)
    if res != 0:
        raise WinError()
    return metrics
 def __init__(self, value=None):
     self._owned = False
     if isinstance(value, c_void_p):
         self._c = _CObjectProxy(value, self._c_api)
     elif value is None or isinstance(value, str):
         _c_ptr = _new(c_sizeof(c_void_p))
         self._c = _CObjectProxy(_c_ptr, self._c_api)
         self._c.QString(value)
         self._owned = True
     else:
         raise TypeError("QString can only be initialized with None, str, or a pointer")
def _from_bn_smart_ptr(ptr, c_type, new_ref):
    if new_ref not in _bn_new_ref_fns:
        _bn_new_ref_fns[new_ref] = _CStaticMethodProxy(new_ref, CFUNCTYPE(c_void_p, c_void_p))
    new_ref_fn = _bn_new_ref_fns[new_ref]

    # The layout of class CoreRefCountObject is as follows:
    #   void* vtbl;
    #   int   m_refs;
    #   T*    m_object;
    # We need m_object.
    c_object = c_cast(ptr + c_sizeof(c_void_p) * 2, CPOINTER(c_void_p)).contents
    return bnc.handle_of_type(c_cast(new_ref_fn(c_object), c_void_p), c_type)
Example #10
0
def query_if(ifname):
   ifname = ifname.encode('ascii')
   sysctl_buf_len = c_uint(0)

   rval = libc.sysctl(mib, 6, None, byref(sysctl_buf_len), None, 0)
   if rval != 0:
      raise Exception(errno.errorcode[get_errno()])

   sysctl_buf = create_string_buffer(sysctl_buf_len.value)
   rval = libc.sysctl(mib, 6, sysctl_buf, byref(sysctl_buf_len), None, 0)
   if rval != 0:
      raise Exception(errno.errorcode[get_errno()])

# walk the structure.  you need to know the length from ifm_msglen
   idx = addressof(sysctl_buf)
   end = idx + sysctl_buf_len.value
   while idx < end:
      batch_off = idx - addressof(sysctl_buf)
      ifmsg = cast(c_void_p(idx), POINTER(if_msghdr2))
      if ifmsg.contents.ifm_type != RTM_IFINFO2:
         idx += ifmsg.contents.ifm_msglen
         continue
      if ifmsg.contents.ifm_flags & IFF_LOOPBACK:
         idx += ifmsg.contents.ifm_msglen
         continue
      # 12 bytes to compensate for 32 bit alignment
      sdl = cast(c_void_p(idx + c_sizeof(if_msghdr2)), POINTER(sockaddr_dl))
      if sdl.contents.sdl_family != AF_LINK:
         idx += ifmsg.contents.ifm_msglen
         continue

      if ifname != sdl.contents.sdl_data[0:sdl.contents.sdl_nlen]:
         idx += ifmsg.contents.ifm_msglen
         continue
      return ifmsg.contents.ifm_data.ifi_ibytes, ifmsg.contents.ifm_data.ifi_obytes
      #idx += ifmsg.contents.ifm_msglen
   raise Exception('ifname {0} not found'.format(ifname))
Example #11
0
def process__get_all_service_information():
    advapi32 = WinDLL('advapi32.dll')
    OpenSCManager = advapi32.OpenSCManagerW
    OpenSCManager.restype = wintypes.DWORD
    EnumServicesStatusEx = advapi32.EnumServicesStatusExW
    # EnumServicesStatusExW(SC_HANDLE,SC_ENUM_TYPE,DWORD,DWORD,LPBYTE,DWORD,LPDWORD,LPDWORD,LPDWORD,LPCWSTR);
    # EnumServicesStatusEx.argtypes = [
    #     c_int,             # hSCManager (SC_HANDLE)
    #     c_int,             # InfoLevel (SC_ENUM_TYPE)
    #     wintypes.DWORD,    # dwServiceType
    #     wintypes.DWORD,    # dwServiceState
    #     wintypes.LPBYTE,   # lpServices
    #     wintypes.DWORD,    # cbBufSize
    #     wintypes.LPDWORD,  # pcbBytesNeeded
    #     wintypes.LPDWORD,  # lpServicesReturned
    #     wintypes.LPDWORD,  # lpResumeHandle
    #     wintypes.LPCWSTR   # pszGroupname
    # ]
    CloseServiceHandle = advapi32.CloseServiceHandle
    CloseServiceHandle.argtypes = [wintypes.HANDLE]

    sc = OpenSCManager(None, None, SC_MANAGER_ENUMERATE_SERVICE)
    if sc == 0:
        raise WinError()
    try:
        bytes_needed = wintypes.DWORD(0)
        service_byte_count = wintypes.DWORD(0)
        service_count = wintypes.DWORD(0)
        resume_handle = wintypes.DWORD(0)
        status_array = None

        # Start off with 0 bytes allocated, and increase from there.
        while True:
            res = EnumServicesStatusEx(
                sc,
                SC_ENUM_PROCESS_INFO,
                # SERVICE_DRIVER | SERVICE_FILE_SYSTEM_DRIVER | SERVICE_KERNEL_DRIVER | SERVICE_WIN32,
                SERVICE_WIN32,
                SERVICE_STATE_ALL,
                status_array,
                service_byte_count,
                byref(bytes_needed),
                byref(service_count),
                byref(resume_handle),
                None)
            if res != 0:
                break
            if GetLastError() != ERROR_MORE_DATA:
                # raise ctypes.WinError()
                return []
            print("need {0} bytes".format(bytes_needed))
            service_byte_count = bytes_needed
            count = bytes_needed.value // c_sizeof(ENUM_SERVICE_STATUS_PROCESS)
            status_array = (ENUM_SERVICE_STATUS_PROCESS * count)()
        ret = []
        for i in range(service_count.value):
            status = status_array[i]
            controls_accepted = []
            if status.dwControlsAccepted & SERVICE_ACCEPT_NETBINDCHANGE == SERVICE_ACCEPT_NETBINDCHANGE:
                controls_accepted.append('SERVICE_ACCEPT_NETBINDCHANGE')
            if status.dwControlsAccepted & SERVICE_ACCEPT_PARAMCHANGE == SERVICE_ACCEPT_PARAMCHANGE:
                controls_accepted.append('SERVICE_ACCEPT_PARAMCHANGE')
            if status.dwControlsAccepted & SERVICE_ACCEPT_PAUSE_CONTINUE == SERVICE_ACCEPT_PAUSE_CONTINUE:
                controls_accepted.append('SERVICE_ACCEPT_PAUSE_CONTINUE')
            if status.dwControlsAccepted & SERVICE_ACCEPT_PRESHUTDOWN == SERVICE_ACCEPT_PRESHUTDOWN:
                controls_accepted.append('SERVICE_ACCEPT_PRESHUTDOWN')
            if status.dwControlsAccepted & SERVICE_ACCEPT_SHUTDOWN == SERVICE_ACCEPT_SHUTDOWN:
                controls_accepted.append('SERVICE_ACCEPT_SHUTDOWN')
            if status.dwControlsAccepted & SERVICE_ACCEPT_STOP == SERVICE_ACCEPT_STOP:
                controls_accepted.append('SERVICE_ACCEPT_STOP')

            ret.append({
                'display_name':
                status.lpServiceName.value,
                'service_name':
                status.lpDisplayName.value,
                'service_type': (status.dwServiceType in _SERVICE_TYPES
                                 and _SERVICE_TYPES[status.dwServiceType]
                                 or None),
                'current_state':
                (status.dwCurrentState in _SERVICE_CURRENT_STATES
                 and _SERVICE_CURRENT_STATES[status.dwCurrentState] or None),
                'controls_accepted':
                controls_accepted,
                'exit_code':
                status.dwWin32ExitCode,
                'service_exit_code':
                status.dwServiceSpecificExitCode,
                'check_point':
                status.dwCheckPoint,
                'wait_time_millis_hint':
                status.dwWaitHint,
                'process_id':
                status.dwProcessId,
                'flags':
                status.dwServiceFlags == 1
                and ['SERVICE_RUNS_IN_SYSTEM_PROCESS'] or [],
            })
        return ret
    finally:
        CloseServiceHandle(sc)
Example #12
0
    def thread_window_callback(hwnd, lparam):
        length = windll.user32.GetWindowTextLengthW(hwnd)
        if length > 0:
            buff = create_unicode_buffer(length + 1)
            windll.user32.GetWindowTextW(hwnd, buff, length + 1)
            # print("DEBUG - Inspecting {0} = {1}".format(hwnd, buff.value))
            if buff.value == "Start":
                # Found the window
                # print("DEBUG sending Click message")
                m_res = windll.user32.SendMessageW(hwnd, BM_CLICK, 0, 0)
                if m_res != 0:
                    # Don't look anymore
                    triggered_start[0] = True
                    return False
                else:
                    try:
                        print("<<ERROR pressing start button>>")
                        raise WinError()
                    except OSError:
                        import traceback
                        traceback.print_exc()
            if buff.value == "Start menu":
                triggered_start[0] = True
                if windll.user32.IsWindowVisible(hwnd):
                    p = WINDOWPLACEMENT()
                    p.length = c_sizeof(WINDOWPLACEMENT)
                    val = windll.user32.GetWindowPlacement(hwnd, byref(p))
                    if val is not None:
                        show_cmd = p.showCmd
                        if (show_cmd == SW_SHOWNORMAL or show_cmd == SW_MAXIMIZE or show_cmd == SW_SHOWMAXIMIZED
                                or show_cmd == SW_SHOWNOACTIVATE or show_cmd == SW_SHOW or show_cmd == SW_SHOWNA
                                or show_cmd == SW_RESTORE):
                            # Hide the window
                            # print("DEBUG hiding the start menu {0}".format(show_cmd))
                            windll.user32.ShowWindow(hwnd, SW_HIDE)
                            return False
                # print("DEBUG showing the start menu ({0})".format(placement.showCmd))
                windll.user32.ShowWindow(hwnd, SW_SHOW)

                # If the task bar is hidden, then part of the start window is not shown fully.
                # SW_MAXIMIZE will show it fully, but the rendering becomes messed up.
                taskbar_rect = wintypes.RECT()
                windll.user32.GetClientRect(taskbar_hwnd, byref(taskbar_rect))

                client_rect = wintypes.RECT()
                windll.user32.GetClientRect(hwnd, byref(client_rect))

                overlap_rect = wintypes.RECT()
                if windll.user32.IntersectRect(byref(overlap_rect), byref(taskbar_rect), byref(client_rect)) != 0:
                    # The taskbar and the start window rectangles overlap each other.
                    # Adjust the start window to be outside of this.
                    # Remember: the taskbar can be anywhere on the edge of the screen.
                    new_x = client_rect.left
                    new_y = client_rect.top
                    if overlap_rect.left == client_rect.left and overlap_rect.right == client_rect.right:
                        # Adjust along the y axis
                        if overlap_rect.top <= client_rect.top <= overlap_rect.bottom:
                            # Adjust down
                            new_y = overlap_rect.bottom
                        else:
                            # Adjust up
                            new_y = client_rect.top - (overlap_rect.bottom - overlap_rect.top)
                    else:
                        # Adjust along the x axis
                        if overlap_rect.left <= client_rect.left <= overlap_rect.right:
                            # Adjust to the right
                            new_x = overlap_rect.right
                        else:
                            new_x = client_rect.left - (overlap_rect.right - overlap_rect.left)
                    windll.user32.SetWindowPos(
                        hwnd, None, new_x, new_y,
                        0, 0, SWP_NOSIZE)

                # Give the window the focus.  This is the Microsoft Magic Focus Dance.
                current_hwnd = windll.user32.GetForegroundWindow()
                current_thread_id = windll.kernel32.GetCurrentThreadId()
                thread_process_id = windll.user32.GetWindowThreadProcessId(current_hwnd, None)
                windll.user32.AttachThreadInput(thread_process_id, current_thread_id, True)
                windll.user32.SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE)
                windll.user32.SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE)
                windll.user32.SetForegroundWindow(hwnd)
                windll.user32.AttachThreadInput(thread_process_id, current_thread_id, False)
                windll.user32.SetFocus(hwnd)
                windll.user32.SetActiveWindow(hwnd)

                return False
        # else:
        #     print("DEBUG - Inspecting {0} => no title, ignoring".format(hwnd))
        return True
Example #13
0
def shell__open_start_menu(show_taskbar):
    # Find the task bar window
    taskbar_hwnd = windll.user32.FindWindowW("Shell_TrayWnd", None)
    if taskbar_hwnd is None or 0 == taskbar_hwnd:
        raise WinError()
    taskbar_size = wintypes.RECT()
    windll.user32.GetWindowRect(taskbar_hwnd, byref(taskbar_size))

    # if show_taskbar:
    #     if windll.user32.IsWindowVisible(taskbar_hwnd):
    #         placement = WINDOWPLACEMENT()
    #         placement.length = c_sizeof(WINDOWPLACEMENT)
    #         val = windll.user32.GetWindowPlacement(taskbar_hwnd, byref(placement))
    #         if val is not None:
    #             show_cmd = placement.showCmd
    #             if (show_cmd == SW_SHOWNORMAL or show_cmd == SW_MAXIMIZE or show_cmd == SW_SHOWMAXIMIZED
    #                     or show_cmd == SW_SHOWNOACTIVATE or show_cmd == SW_SHOW or show_cmd == SW_SHOWNA
    #                     or show_cmd == SW_RESTORE):
    #                 show_taskbar = False
    if show_taskbar:
        # The task bar is auto-hide.  It's always present, but not on screen.
        # The trick Windows uses is pushing it off-screen, so it's just barely
        # visible.

        windll.user32.GetWindowRect(taskbar_hwnd, byref(taskbar_size))
        # Figure out which corner it's in.  It's either top, left, right, or bottom.
        # We do this by finding a "0", which indicates where on the screen it's
        # located.  However, with strange, multi-monitor setups, this isn't always
        # correct.  But it's a good guess.
        # windll.user32.SetWindowPos(taskbar_hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW)

        # TODO show the task bar.
        # print("<<Don't know how to show the task bar>>")

    # Find the process ID of the taskbar window.
    taskbar_pid = wintypes.DWORD()
    windll.user32.GetWindowThreadProcessId(taskbar_hwnd, byref(taskbar_pid))

    # Find a thread in that process that has a "Start" button
    triggered_start = [False]

    # noinspection PyUnusedLocal
    def thread_window_callback(hwnd, lparam):
        length = windll.user32.GetWindowTextLengthW(hwnd)
        if length > 0:
            buff = create_unicode_buffer(length + 1)
            windll.user32.GetWindowTextW(hwnd, buff, length + 1)
            # print("DEBUG - Inspecting {0} = {1}".format(hwnd, buff.value))
            if buff.value == "Start":
                # Found the window
                # print("DEBUG sending Click message")
                m_res = windll.user32.SendMessageW(hwnd, BM_CLICK, 0, 0)
                if m_res != 0:
                    # Don't look anymore
                    triggered_start[0] = True
                    return False
                else:
                    try:
                        print("<<ERROR pressing start button>>")
                        raise WinError()
                    except OSError:
                        import traceback
                        traceback.print_exc()
            if buff.value == "Start menu":
                triggered_start[0] = True
                if windll.user32.IsWindowVisible(hwnd):
                    p = WINDOWPLACEMENT()
                    p.length = c_sizeof(WINDOWPLACEMENT)
                    val = windll.user32.GetWindowPlacement(hwnd, byref(p))
                    if val is not None:
                        show_cmd = p.showCmd
                        if (show_cmd == SW_SHOWNORMAL or show_cmd == SW_MAXIMIZE or show_cmd == SW_SHOWMAXIMIZED
                                or show_cmd == SW_SHOWNOACTIVATE or show_cmd == SW_SHOW or show_cmd == SW_SHOWNA
                                or show_cmd == SW_RESTORE):
                            # Hide the window
                            # print("DEBUG hiding the start menu {0}".format(show_cmd))
                            windll.user32.ShowWindow(hwnd, SW_HIDE)
                            return False
                # print("DEBUG showing the start menu ({0})".format(placement.showCmd))
                windll.user32.ShowWindow(hwnd, SW_SHOW)

                # If the task bar is hidden, then part of the start window is not shown fully.
                # SW_MAXIMIZE will show it fully, but the rendering becomes messed up.
                taskbar_rect = wintypes.RECT()
                windll.user32.GetClientRect(taskbar_hwnd, byref(taskbar_rect))

                client_rect = wintypes.RECT()
                windll.user32.GetClientRect(hwnd, byref(client_rect))

                overlap_rect = wintypes.RECT()
                if windll.user32.IntersectRect(byref(overlap_rect), byref(taskbar_rect), byref(client_rect)) != 0:
                    # The taskbar and the start window rectangles overlap each other.
                    # Adjust the start window to be outside of this.
                    # Remember: the taskbar can be anywhere on the edge of the screen.
                    new_x = client_rect.left
                    new_y = client_rect.top
                    if overlap_rect.left == client_rect.left and overlap_rect.right == client_rect.right:
                        # Adjust along the y axis
                        if overlap_rect.top <= client_rect.top <= overlap_rect.bottom:
                            # Adjust down
                            new_y = overlap_rect.bottom
                        else:
                            # Adjust up
                            new_y = client_rect.top - (overlap_rect.bottom - overlap_rect.top)
                    else:
                        # Adjust along the x axis
                        if overlap_rect.left <= client_rect.left <= overlap_rect.right:
                            # Adjust to the right
                            new_x = overlap_rect.right
                        else:
                            new_x = client_rect.left - (overlap_rect.right - overlap_rect.left)
                    windll.user32.SetWindowPos(
                        hwnd, None, new_x, new_y,
                        0, 0, SWP_NOSIZE)

                # Give the window the focus.  This is the Microsoft Magic Focus Dance.
                current_hwnd = windll.user32.GetForegroundWindow()
                current_thread_id = windll.kernel32.GetCurrentThreadId()
                thread_process_id = windll.user32.GetWindowThreadProcessId(current_hwnd, None)
                windll.user32.AttachThreadInput(thread_process_id, current_thread_id, True)
                windll.user32.SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE)
                windll.user32.SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE)
                windll.user32.SetForegroundWindow(hwnd)
                windll.user32.AttachThreadInput(thread_process_id, current_thread_id, False)
                windll.user32.SetFocus(hwnd)
                windll.user32.SetActiveWindow(hwnd)

                return False
        # else:
        #     print("DEBUG - Inspecting {0} => no title, ignoring".format(hwnd))
        return True

    # Find the threads for the process ID
    thread_ids = []
    hsnapshot = windll.kernel32.CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, taskbar_pid)
    if hsnapshot == INVALID_HANDLE_VALUE:
        raise WinError()
    try:
        thread_entry = THREADENTRY32()
        thread_entry.dwSize = c_sizeof(THREADENTRY32)

        # print("DEBUG Getting threads for pid {0}".format(taskbar_pid))
        res = windll.kernel32.Thread32First(hsnapshot, byref(thread_entry))
        # print("DEBUG :: first: {0}".format(res))
        if res == 0:
            raise WinError()
        while res != 0:
            if thread_entry.dwSize > THREADENTRY32.th32OwnerProcessID.offset:
                thread_ids.append(thread_entry.th32ThreadID)
            # else:
            #     print("DEBUG - returned too small size {0}".format(thread_entry.dwSize))
            thread_entry.dwSize = c_sizeof(THREADENTRY32)
            res = windll.kernel32.Thread32Next(hsnapshot, byref(thread_entry))
            # print("DEBUG :: next: {0}".format(res))
    finally:
        windll.kernel32.CloseHandle(hsnapshot)

    callback_type = CFUNCTYPE(wintypes.BOOL, wintypes.HWND, wintypes.LPARAM)
    callback_ptr = callback_type(thread_window_callback)
    for thread_id in thread_ids:
        # print("DEBUG Iterating over windows for thread {0} in pid {1}".format(thread_id, taskbar_pid))
        windll.user32.EnumThreadWindows(thread_id, callback_ptr, 0)
        if triggered_start[0]:
            return

    raise OSError("Could not find start button")