win32.py 2.2 KB

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