1from ctypes import pointer 2 3from ..utils import SPHINX_AUTODOC_RUNNING 4 5# Do not import win32-specific stuff when generating documentation. 6# Otherwise RTD would be unable to generate docs for this module. 7if not SPHINX_AUTODOC_RUNNING: 8 from ctypes import windll 9 10from ctypes.wintypes import BOOL, DWORD, HANDLE 11from typing import List, Optional 12 13from prompt_toolkit.win32_types import SECURITY_ATTRIBUTES 14 15__all__ = ["wait_for_handles", "create_win32_event"] 16 17 18WAIT_TIMEOUT = 0x00000102 19INFINITE = -1 20 21 22def wait_for_handles( 23 handles: List[HANDLE], timeout: int = INFINITE 24) -> Optional[HANDLE]: 25 """ 26 Waits for multiple handles. (Similar to 'select') Returns the handle which is ready. 27 Returns `None` on timeout. 28 http://msdn.microsoft.com/en-us/library/windows/desktop/ms687025(v=vs.85).aspx 29 30 Note that handles should be a list of `HANDLE` objects, not integers. See 31 this comment in the patch by @quark-zju for the reason why: 32 33 ''' Make sure HANDLE on Windows has a correct size 34 35 Previously, the type of various HANDLEs are native Python integer 36 types. The ctypes library will treat them as 4-byte integer when used 37 in function arguments. On 64-bit Windows, HANDLE is 8-byte and usually 38 a small integer. Depending on whether the extra 4 bytes are zero-ed out 39 or not, things can happen to work, or break. ''' 40 41 This function returns either `None` or one of the given `HANDLE` objects. 42 (The return value can be tested with the `is` operator.) 43 """ 44 arrtype = HANDLE * len(handles) 45 handle_array = arrtype(*handles) 46 47 ret: int = windll.kernel32.WaitForMultipleObjects( 48 len(handle_array), handle_array, BOOL(False), DWORD(timeout) 49 ) 50 51 if ret == WAIT_TIMEOUT: 52 return None 53 else: 54 return handles[ret] 55 56 57def create_win32_event() -> HANDLE: 58 """ 59 Creates a Win32 unnamed Event . 60 http://msdn.microsoft.com/en-us/library/windows/desktop/ms682396(v=vs.85).aspx 61 """ 62 return HANDLE( 63 windll.kernel32.CreateEventA( 64 pointer(SECURITY_ATTRIBUTES()), 65 BOOL(True), # Manual reset event. 66 BOOL(False), # Initial state. 67 None, # Unnamed event object. 68 ) 69 ) 70