// Copyright (c) 2016 Klemens D. Morgenstern // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_DETAIL_WINDOWS_JOB_WORKAROUND_HPP_ #define BOOST_PROCESS_DETAIL_WINDOWS_JOB_WORKAROUND_HPP_ #include #include #include #include #if defined( BOOST_USE_WINDOWS_H ) #include #else extern "C" { BOOST_SYMBOL_IMPORT ::boost::winapi::HANDLE_ BOOST_WINAPI_WINAPI_CC CreateIoCompletionPort( ::boost::winapi::HANDLE_ FileHandle, ::boost::winapi::HANDLE_ ExistingCompletionPort, ::boost::winapi::ULONG_PTR_ CompletionKey, ::boost::winapi::DWORD_ NumberOfConcurrentThreads ); BOOST_SYMBOL_IMPORT ::boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC GetQueuedCompletionStatus( ::boost::winapi::HANDLE_ CompletionPort, ::boost::winapi::LPDWORD_ lpNumberOfBytes, ::boost::winapi::ULONG_PTR_ *lpCompletionKey, _OVERLAPPED **lpOverlapped, ::boost::winapi::DWORD_ dwMilliseconds ); } #endif namespace boost { namespace process { namespace detail { namespace windows { namespace workaround { extern "C" { struct JOBOBJECT_ASSOCIATE_COMPLETION_PORT_ { ::boost::winapi::PVOID_ CompletionKey; ::boost::winapi::HANDLE_ CompletionPort; }; constexpr static int JOB_OBJECT_MSG_END_OF_JOB_TIME_ = 1; constexpr static int JOB_OBJECT_MSG_END_OF_PROCESS_TIME_ = 2; constexpr static int JOB_OBJECT_MSG_ACTIVE_PROCESS_LIMIT_ = 3; constexpr static int JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO_ = 4; constexpr static int JOB_OBJECT_MSG_NEW_PROCESS_ = 6; constexpr static int JOB_OBJECT_MSG_EXIT_PROCESS_ = 7; constexpr static int JOB_OBJECT_MSG_ABNORMAL_EXIT_PROCESS_ = 8; constexpr static int JOB_OBJECT_MSG_PROCESS_MEMORY_LIMIT_ = 9; constexpr static int JOB_OBJECT_MSG_JOB_MEMORY_LIMIT_ = 10; constexpr static int JOB_OBJECT_MSG_NOTIFICATION_LIMIT_ = 11; constexpr static int JOB_OBJECT_MSG_JOB_CYCLE_TIME_LIMIT_ = 12; constexpr static int JOB_OBJECT_MSG_SILO_TERMINATED_ = 13; } BOOST_FORCEINLINE ::boost::winapi::BOOL_ get_queued_completion_status( ::boost::winapi::HANDLE_ CompletionPort, ::boost::winapi::LPDWORD_ lpNumberOfBytes, ::boost::winapi::ULONG_PTR_ *lpCompletionKey, ::boost::winapi::LPOVERLAPPED_ *lpOverlapped, ::boost::winapi::DWORD_ dwMilliseconds) { return ::GetQueuedCompletionStatus( CompletionPort, lpNumberOfBytes, lpCompletionKey, reinterpret_cast<::_OVERLAPPED**>(lpOverlapped), dwMilliseconds); } #if defined( BOOST_USE_WINDOWS_H ) constexpr auto static JobObjectExtendedLimitInformation_ = ::JobObjectExtendedLimitInformation; constexpr auto static JobObjectAssociateCompletionPortInformation_ = ::JobObjectAssociateCompletionPortInformation; constexpr auto static JobObjectBasicAccountingInformation_ = ::JobObjectBasicAccountingInformation; using JOBOBJECT_BASIC_LIMIT_INFORMATION_ = ::JOBOBJECT_BASIC_LIMIT_INFORMATION; using JOBOBJECTINFOCLASS_ = ::JOBOBJECTINFOCLASS; using IO_COUNTERS_ = ::IO_COUNTERS; using JOBOBJECT_EXTENDED_LIMIT_INFORMATION_ = ::JOBOBJECT_EXTENDED_LIMIT_INFORMATION; using JOBOBJECT_BASIC_ACCOUNTING_INFORMATION_ = ::JOBOBJECT_BASIC_ACCOUNTING_INFORMATION; inline ::boost::winapi::BOOL_ query_information_job_object( ::boost::winapi::HANDLE_ hJob, JOBOBJECTINFOCLASS_ JobObjectInfoClass, void * lpJobObjectInfo, ::boost::winapi::DWORD_ cbJobObjectInfoLength, ::boost::winapi::DWORD_ *lpReturnLength) { return ::QueryInformationJobObject(hJob, JobObjectInfoClass, lpJobObjectInfo, cbJobObjectInfoLength, lpReturnLength); } inline ::boost::winapi::BOOL_ set_information_job_object( ::boost::winapi::HANDLE_ hJob, JOBOBJECTINFOCLASS_ JobObjectInfoClass, void * lpJobObjectInfo, ::boost::winapi::DWORD_ cbJobObjectInfoLength) { return ::SetInformationJobObject(hJob, JobObjectInfoClass, lpJobObjectInfo, cbJobObjectInfoLength); } #else //this import workaround is to keep it a header-only library. and enums cannot be imported from the winapi. extern "C" { typedef enum _JOBOBJECTINFOCLASS_ { JobObjectBasicAccountingInformation_ = 1, JobObjectBasicLimitInformation_, JobObjectBasicProcessIdList_, JobObjectBasicUIRestrictions_, JobObjectSecurityLimitInformation_, JobObjectEndOfJobTimeInformation_, JobObjectAssociateCompletionPortInformation_, JobObjectBasicAndIoAccountingInformation_, JobObjectExtendedLimitInformation_, JobObjectJobSetInformation_, JobObjectGroupInformation_, JobObjectNotificationLimitInformation_, JobObjectLimitViolationInformation_, JobObjectGroupInformationEx_, JobObjectCpuRateControlInformation_, JobObjectCompletionFilter_, JobObjectCompletionCounter_, JobObjectReserved1Information_ = 18, JobObjectReserved2Information_, JobObjectReserved3Information_, JobObjectReserved4Information_, JobObjectReserved5Information_, JobObjectReserved6Information_, JobObjectReserved7Information_, JobObjectReserved8Information_, MaxJobObjectInfoClass_ } JOBOBJECTINFOCLASS_; typedef struct _JOBOBJECT_BASIC_LIMIT_INFORMATION_ { ::boost::winapi::LARGE_INTEGER_ PerProcessUserTimeLimit; ::boost::winapi::LARGE_INTEGER_ PerJobUserTimeLimit; ::boost::winapi::DWORD_ LimitFlags; ::boost::winapi::SIZE_T_ MinimumWorkingSetSize; ::boost::winapi::SIZE_T_ MaximumWorkingSetSize; ::boost::winapi::DWORD_ ActiveProcessLimit; ::boost::winapi::ULONG_PTR_ Affinity; ::boost::winapi::DWORD_ PriorityClass; ::boost::winapi::DWORD_ SchedulingClass; } JOBOBJECT_BASIC_LIMIT_INFORMATION_; typedef struct _JOBOBJECT_BASIC_ACCOUNTING_INFORMATION_ { ::boost::winapi::LARGE_INTEGER_ TotalUserTime; ::boost::winapi::LARGE_INTEGER_ TotalKernelTime; ::boost::winapi::LARGE_INTEGER_ ThisPeriodTotalUserTime; ::boost::winapi::LARGE_INTEGER_ ThisPeriodTotalKernelTime; ::boost::winapi::DWORD_ TotalPageFaultCount; ::boost::winapi::DWORD_ TotalProcesses; ::boost::winapi::DWORD_ ActiveProcesses; ::boost::winapi::DWORD_ TotalTerminatedProcesses; } JOBOBJECT_BASIC_ACCOUNTING_INFORMATION_; typedef struct _IO_COUNTERS_ { ::boost::winapi::ULONGLONG_ ReadOperationCount; ::boost::winapi::ULONGLONG_ WriteOperationCount; ::boost::winapi::ULONGLONG_ OtherOperationCount; ::boost::winapi::ULONGLONG_ ReadTransferCount; ::boost::winapi::ULONGLONG_ WriteTransferCount; ::boost::winapi::ULONGLONG_ OtherTransferCount; } IO_COUNTERS_; typedef struct _JOBOBJECT_EXTENDED_LIMIT_INFORMATION_ { JOBOBJECT_BASIC_LIMIT_INFORMATION_ BasicLimitInformation; IO_COUNTERS_ IoInfo; ::boost::winapi::SIZE_T_ ProcessMemoryLimit; ::boost::winapi::SIZE_T_ JobMemoryLimit; ::boost::winapi::SIZE_T_ PeakProcessMemoryUsed; ::boost::winapi::SIZE_T_ PeakJobMemoryUsed; } JOBOBJECT_EXTENDED_LIMIT_INFORMATION_; /*BOOL WINAPI QueryInformationJobObject( _In_opt_ HANDLE hJob, _In_ JOBOBJECTINFOCLASS JobObjectInfoClass, _Out_ LPVOID lpJobObjectInfo, _In_ DWORD cbJobObjectInfoLength, _Out_opt_ LPDWORD lpReturnLength ); */ typedef ::boost::winapi::BOOL_ (BOOST_WINAPI_WINAPI_CC *query_information_job_object_p)( ::boost::winapi::HANDLE_, JOBOBJECTINFOCLASS_, void *, ::boost::winapi::DWORD_, ::boost::winapi::DWORD_ *); inline ::boost::winapi::BOOL_ query_information_job_object( ::boost::winapi::HANDLE_ hJob, JOBOBJECTINFOCLASS_ JobObjectInfoClass, void *lpJobObjectInfo, ::boost::winapi::DWORD_ cbJobObjectInfoLength, ::boost::winapi::DWORD_ *lpReturnLength) { static ::boost::winapi::HMODULE_ h = ::boost::winapi::get_module_handle( L"Kernel32.dll"); static query_information_job_object_p f = reinterpret_cast(::boost::winapi::get_proc_address( h, "QueryInformationJobObject")); return (*f)(hJob, JobObjectInfoClass, lpJobObjectInfo, cbJobObjectInfoLength, lpReturnLength); } /*BOOL WINAPI SetInformationJobObject( _In_ HANDLE hJob, _In_ JOBOBJECTINFOCLASS JobObjectInfoClass, _In_ LPVOID lpJobObjectInfo, _In_ DWORD cbJobObjectInfoLength );*/ typedef ::boost::winapi::BOOL_ (BOOST_WINAPI_WINAPI_CC *set_information_job_object_p)( ::boost::winapi::HANDLE_, JOBOBJECTINFOCLASS_, void *, ::boost::winapi::DWORD_); } inline ::boost::winapi::BOOL_ set_information_job_object( ::boost::winapi::HANDLE_ hJob, JOBOBJECTINFOCLASS_ JobObjectInfoClass, void *lpJobObjectInfo, ::boost::winapi::DWORD_ cbJobObjectInfoLength) { static ::boost::winapi::HMODULE_ h = ::boost::winapi::get_module_handle( L"Kernel32.dll"); static set_information_job_object_p f = reinterpret_cast(::boost::winapi::get_proc_address( h, "SetInformationJobObject")); return (*f)(hJob, JobObjectInfoClass, lpJobObjectInfo, cbJobObjectInfoLength); } #endif constexpr static ::boost::winapi::DWORD_ JOB_OBJECT_LIMIT_BREAKAWAY_OK_ = 0x00000800; }}}}} #endif /* BOOST_PROCESS_DETAIL_WINDOWS_JOB_WORKAROUND_HPP_ */