winapi.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. # Copyright (c) Microsoft Corporation. All rights reserved.
  2. # Licensed under the MIT License. See LICENSE in the project root
  3. # for license information.
  4. import ctypes
  5. from ctypes.wintypes import BOOL, DWORD, HANDLE, LARGE_INTEGER, LPCSTR, UINT
  6. from debugpy.common import log
  7. JOBOBJECTCLASS = ctypes.c_int
  8. LPDWORD = ctypes.POINTER(DWORD)
  9. LPVOID = ctypes.c_void_p
  10. SIZE_T = ctypes.c_size_t
  11. ULONGLONG = ctypes.c_ulonglong
  12. class IO_COUNTERS(ctypes.Structure):
  13. _fields_ = [
  14. ("ReadOperationCount", ULONGLONG),
  15. ("WriteOperationCount", ULONGLONG),
  16. ("OtherOperationCount", ULONGLONG),
  17. ("ReadTransferCount", ULONGLONG),
  18. ("WriteTransferCount", ULONGLONG),
  19. ("OtherTransferCount", ULONGLONG),
  20. ]
  21. class JOBOBJECT_BASIC_LIMIT_INFORMATION(ctypes.Structure):
  22. _fields_ = [
  23. ("PerProcessUserTimeLimit", LARGE_INTEGER),
  24. ("PerJobUserTimeLimit", LARGE_INTEGER),
  25. ("LimitFlags", DWORD),
  26. ("MinimumWorkingSetSize", SIZE_T),
  27. ("MaximumWorkingSetSize", SIZE_T),
  28. ("ActiveProcessLimit", DWORD),
  29. ("Affinity", SIZE_T),
  30. ("PriorityClass", DWORD),
  31. ("SchedulingClass", DWORD),
  32. ]
  33. class JOBOBJECT_EXTENDED_LIMIT_INFORMATION(ctypes.Structure):
  34. _fields_ = [
  35. ("BasicLimitInformation", JOBOBJECT_BASIC_LIMIT_INFORMATION),
  36. ("IoInfo", IO_COUNTERS),
  37. ("ProcessMemoryLimit", SIZE_T),
  38. ("JobMemoryLimit", SIZE_T),
  39. ("PeakProcessMemoryUsed", SIZE_T),
  40. ("PeakJobMemoryUsed", SIZE_T),
  41. ]
  42. JobObjectExtendedLimitInformation = JOBOBJECTCLASS(9)
  43. JOB_OBJECT_LIMIT_BREAKAWAY_OK = 0x00000800
  44. JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE = 0x00002000
  45. PROCESS_TERMINATE = 0x0001
  46. PROCESS_SET_QUOTA = 0x0100
  47. def _errcheck(is_error_result=(lambda result: not result)):
  48. def impl(result, func, args):
  49. if is_error_result(result):
  50. log.debug("{0} returned {1}", func.__name__, result)
  51. raise ctypes.WinError()
  52. else:
  53. return result
  54. return impl
  55. kernel32 = ctypes.windll.kernel32
  56. kernel32.AssignProcessToJobObject.errcheck = _errcheck()
  57. kernel32.AssignProcessToJobObject.restype = BOOL
  58. kernel32.AssignProcessToJobObject.argtypes = (HANDLE, HANDLE)
  59. kernel32.CreateJobObjectA.errcheck = _errcheck(lambda result: result == 0)
  60. kernel32.CreateJobObjectA.restype = HANDLE
  61. kernel32.CreateJobObjectA.argtypes = (LPVOID, LPCSTR)
  62. kernel32.OpenProcess.errcheck = _errcheck(lambda result: result == 0)
  63. kernel32.OpenProcess.restype = HANDLE
  64. kernel32.OpenProcess.argtypes = (DWORD, BOOL, DWORD)
  65. kernel32.QueryInformationJobObject.errcheck = _errcheck()
  66. kernel32.QueryInformationJobObject.restype = BOOL
  67. kernel32.QueryInformationJobObject.argtypes = (
  68. HANDLE,
  69. JOBOBJECTCLASS,
  70. LPVOID,
  71. DWORD,
  72. LPDWORD,
  73. )
  74. kernel32.SetInformationJobObject.errcheck = _errcheck()
  75. kernel32.SetInformationJobObject.restype = BOOL
  76. kernel32.SetInformationJobObject.argtypes = (HANDLE, JOBOBJECTCLASS, LPVOID, DWORD)
  77. kernel32.TerminateJobObject.errcheck = _errcheck()
  78. kernel32.TerminateJobObject.restype = BOOL
  79. kernel32.TerminateJobObject.argtypes = (HANDLE, UINT)