_winapi.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. """
  2. Support routines for subprocess module.
  3. Currently, this extension module is only required when using the
  4. subprocess module on Windows.
  5. """
  6. import sys
  7. if sys.platform != 'win32':
  8. raise ImportError("The '_subprocess' module is only available on Windows")
  9. # Declare external Win32 functions
  10. from _pypy_winbase_cffi import ffi as _ffi
  11. _kernel32 = _ffi.dlopen('kernel32')
  12. GetVersion = _kernel32.GetVersion
  13. # Now the _subprocess module implementation
  14. def _WinError():
  15. code, message = _ffi.getwinerror()
  16. raise WindowsError(code, message)
  17. def _int2handle(val):
  18. return _ffi.cast("HANDLE", val)
  19. def _handle2int(handle):
  20. return int(_ffi.cast("intptr_t", handle))
  21. _INVALID_HANDLE_VALUE = _int2handle(-1)
  22. def CreatePipe(attributes, size):
  23. handles = _ffi.new("HANDLE[2]")
  24. res = _kernel32.CreatePipe(handles, handles + 1, _ffi.NULL, size)
  25. if not res:
  26. raise _WinError()
  27. return _handle2int(handles[0]), _handle2int(handles[1])
  28. def GetCurrentProcess():
  29. return _handle2int(_kernel32.GetCurrentProcess())
  30. def DuplicateHandle(source_process, source, target_process, access, inherit, options=0):
  31. # CPython: the first three arguments are expected to be integers
  32. target = _ffi.new("HANDLE[1]")
  33. res = _kernel32.DuplicateHandle(
  34. _int2handle(source_process),
  35. _int2handle(source),
  36. _int2handle(target_process),
  37. target, access, inherit, options)
  38. if not res:
  39. raise _WinError()
  40. return _handle2int(target[0])
  41. def _Z(input):
  42. if input is None:
  43. return _ffi.NULL
  44. if isinstance(input, str):
  45. return input
  46. raise TypeError("str or None expected, got %r" % (
  47. type(input).__name__,))
  48. def CreateProcess(name, command_line, process_attr, thread_attr,
  49. inherit, flags, env, start_dir, startup_info):
  50. si = _ffi.new("STARTUPINFO *")
  51. if startup_info is not None:
  52. si.dwFlags = startup_info.dwFlags
  53. si.wShowWindow = startup_info.wShowWindow
  54. # CPython: these three handles are expected to be
  55. # subprocess.Handle (int) objects
  56. if startup_info.hStdInput:
  57. si.hStdInput = _int2handle(startup_info.hStdInput)
  58. if startup_info.hStdOutput:
  59. si.hStdOutput = _int2handle(startup_info.hStdOutput)
  60. if startup_info.hStdError:
  61. si.hStdError = _int2handle(startup_info.hStdError)
  62. pi = _ffi.new("PROCESS_INFORMATION *")
  63. flags |= CREATE_UNICODE_ENVIRONMENT
  64. if env is not None:
  65. envbuf = ""
  66. for k, v in env.items():
  67. envbuf += "%s=%s\0" % (k, v)
  68. envbuf += '\0'
  69. else:
  70. envbuf = _ffi.NULL
  71. res = _kernel32.CreateProcessW(_Z(name), _Z(command_line), _ffi.NULL,
  72. _ffi.NULL, inherit, flags, envbuf,
  73. _Z(start_dir), si, pi)
  74. if not res:
  75. raise _WinError()
  76. return (_handle2int(pi.hProcess),
  77. _handle2int(pi.hThread),
  78. pi.dwProcessId,
  79. pi.dwThreadId)
  80. def WaitForSingleObject(handle, milliseconds):
  81. # CPython: the first argument is expected to be an integer.
  82. res = _kernel32.WaitForSingleObject(_int2handle(handle), milliseconds)
  83. if res < 0:
  84. raise _WinError()
  85. return res
  86. def GetExitCodeProcess(handle):
  87. # CPython: the first argument is expected to be an integer.
  88. code = _ffi.new("DWORD[1]")
  89. res = _kernel32.GetExitCodeProcess(_int2handle(handle), code)
  90. if not res:
  91. raise _WinError()
  92. return code[0]
  93. def TerminateProcess(handle, exitcode):
  94. # CPython: the first argument is expected to be an integer.
  95. # The second argument is silently wrapped in a UINT.
  96. res = _kernel32.TerminateProcess(_int2handle(handle),
  97. _ffi.cast("UINT", exitcode))
  98. if not res:
  99. raise _WinError()
  100. def GetStdHandle(stdhandle):
  101. stdhandle = _ffi.cast("DWORD", stdhandle)
  102. res = _kernel32.GetStdHandle(stdhandle)
  103. if not res:
  104. return None
  105. else:
  106. return _handle2int(res)
  107. def CloseHandle(handle):
  108. res = _kernel32.CloseHandle(_int2handle(handle))
  109. if not res:
  110. raise _WinError()
  111. def GetModuleFileName(module):
  112. buf = _ffi.new("wchar_t[]", _MAX_PATH)
  113. res = _kernel32.GetModuleFileNameW(_int2handle(module), buf, _MAX_PATH)
  114. if not res:
  115. raise _WinError()
  116. return _ffi.string(buf)
  117. STD_INPUT_HANDLE = -10
  118. STD_OUTPUT_HANDLE = -11
  119. STD_ERROR_HANDLE = -12
  120. DUPLICATE_SAME_ACCESS = 2
  121. STARTF_USESTDHANDLES = 0x100
  122. STARTF_USESHOWWINDOW = 0x001
  123. SW_HIDE = 0
  124. INFINITE = 0xffffffff
  125. WAIT_OBJECT_0 = 0
  126. WAIT_TIMEOUT = 0x102
  127. CREATE_NEW_CONSOLE = 0x010
  128. CREATE_NEW_PROCESS_GROUP = 0x200
  129. CREATE_UNICODE_ENVIRONMENT = 0x400
  130. STILL_ACTIVE = 259
  131. _MAX_PATH = 260