1 // Copyright (c) 2016 Klemens D. Morgenstern
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6 #ifndef BOOST_PROCESS_DETAIL_WINDOWS_JOB_WORKAROUND_HPP_
7 #define BOOST_PROCESS_DETAIL_WINDOWS_JOB_WORKAROUND_HPP_
8
9 #include <boost/winapi/config.hpp>
10 #include <boost/winapi/basic_types.hpp>
11 #include <boost/winapi/dll.hpp>
12 #include <boost/winapi/overlapped.hpp>
13
14 #if defined( BOOST_USE_WINDOWS_H )
15 #include <windows.h>
16 #else
17 extern "C"
18 {
19 BOOST_SYMBOL_IMPORT ::boost::winapi::HANDLE_ BOOST_WINAPI_WINAPI_CC CreateIoCompletionPort(
20 ::boost::winapi::HANDLE_ FileHandle,
21 ::boost::winapi::HANDLE_ ExistingCompletionPort,
22 ::boost::winapi::ULONG_PTR_ CompletionKey,
23 ::boost::winapi::DWORD_ NumberOfConcurrentThreads
24 );
25
26 BOOST_SYMBOL_IMPORT ::boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC GetQueuedCompletionStatus(
27 ::boost::winapi::HANDLE_ CompletionPort,
28 ::boost::winapi::LPDWORD_ lpNumberOfBytes,
29 ::boost::winapi::ULONG_PTR_ *lpCompletionKey,
30 _OVERLAPPED **lpOverlapped,
31 ::boost::winapi::DWORD_ dwMilliseconds
32 );
33
34 }
35 #endif
36 namespace boost { namespace process { namespace detail { namespace windows { namespace workaround {
37
38 extern "C"
39 {
40
41 struct JOBOBJECT_ASSOCIATE_COMPLETION_PORT_
42 {
43 ::boost::winapi::PVOID_ CompletionKey;
44 ::boost::winapi::HANDLE_ CompletionPort;
45 };
46
47 constexpr static int JOB_OBJECT_MSG_END_OF_JOB_TIME_ = 1;
48 constexpr static int JOB_OBJECT_MSG_END_OF_PROCESS_TIME_ = 2;
49 constexpr static int JOB_OBJECT_MSG_ACTIVE_PROCESS_LIMIT_ = 3;
50 constexpr static int JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO_ = 4;
51 constexpr static int JOB_OBJECT_MSG_NEW_PROCESS_ = 6;
52 constexpr static int JOB_OBJECT_MSG_EXIT_PROCESS_ = 7;
53 constexpr static int JOB_OBJECT_MSG_ABNORMAL_EXIT_PROCESS_ = 8;
54 constexpr static int JOB_OBJECT_MSG_PROCESS_MEMORY_LIMIT_ = 9;
55 constexpr static int JOB_OBJECT_MSG_JOB_MEMORY_LIMIT_ = 10;
56 constexpr static int JOB_OBJECT_MSG_NOTIFICATION_LIMIT_ = 11;
57 constexpr static int JOB_OBJECT_MSG_JOB_CYCLE_TIME_LIMIT_ = 12;
58 constexpr static int JOB_OBJECT_MSG_SILO_TERMINATED_ = 13;
59
60 }
61
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)62 BOOST_FORCEINLINE ::boost::winapi::BOOL_ get_queued_completion_status(
63 ::boost::winapi::HANDLE_ CompletionPort,
64 ::boost::winapi::LPDWORD_ lpNumberOfBytes,
65 ::boost::winapi::ULONG_PTR_ *lpCompletionKey,
66 ::boost::winapi::LPOVERLAPPED_ *lpOverlapped,
67 ::boost::winapi::DWORD_ dwMilliseconds)
68 {
69 return ::GetQueuedCompletionStatus(
70 CompletionPort,
71 lpNumberOfBytes,
72 lpCompletionKey,
73 reinterpret_cast<::_OVERLAPPED**>(lpOverlapped),
74 dwMilliseconds);
75 }
76
77 #if defined( BOOST_USE_WINDOWS_H )
78
79 constexpr auto static JobObjectExtendedLimitInformation_ = ::JobObjectExtendedLimitInformation;
80 constexpr auto static JobObjectAssociateCompletionPortInformation_ = ::JobObjectAssociateCompletionPortInformation;
81 constexpr auto static JobObjectBasicAccountingInformation_ = ::JobObjectBasicAccountingInformation;
82
83 using JOBOBJECT_BASIC_LIMIT_INFORMATION_ = ::JOBOBJECT_BASIC_LIMIT_INFORMATION;
84 using JOBOBJECTINFOCLASS_ = ::JOBOBJECTINFOCLASS;
85 using IO_COUNTERS_ = ::IO_COUNTERS;
86 using JOBOBJECT_EXTENDED_LIMIT_INFORMATION_ = ::JOBOBJECT_EXTENDED_LIMIT_INFORMATION;
87 using JOBOBJECT_BASIC_ACCOUNTING_INFORMATION_ = ::JOBOBJECT_BASIC_ACCOUNTING_INFORMATION;
88
query_information_job_object(::boost::winapi::HANDLE_ hJob,JOBOBJECTINFOCLASS_ JobObjectInfoClass,void * lpJobObjectInfo,::boost::winapi::DWORD_ cbJobObjectInfoLength,::boost::winapi::DWORD_ * lpReturnLength)89 inline ::boost::winapi::BOOL_ query_information_job_object(
90 ::boost::winapi::HANDLE_ hJob,
91 JOBOBJECTINFOCLASS_ JobObjectInfoClass,
92 void * lpJobObjectInfo,
93 ::boost::winapi::DWORD_ cbJobObjectInfoLength,
94 ::boost::winapi::DWORD_ *lpReturnLength)
95 {
96 return ::QueryInformationJobObject(hJob, JobObjectInfoClass, lpJobObjectInfo, cbJobObjectInfoLength, lpReturnLength);
97 }
98
set_information_job_object(::boost::winapi::HANDLE_ hJob,JOBOBJECTINFOCLASS_ JobObjectInfoClass,void * lpJobObjectInfo,::boost::winapi::DWORD_ cbJobObjectInfoLength)99 inline ::boost::winapi::BOOL_ set_information_job_object(
100 ::boost::winapi::HANDLE_ hJob,
101 JOBOBJECTINFOCLASS_ JobObjectInfoClass,
102 void * lpJobObjectInfo,
103 ::boost::winapi::DWORD_ cbJobObjectInfoLength)
104 {
105 return ::SetInformationJobObject(hJob, JobObjectInfoClass, lpJobObjectInfo, cbJobObjectInfoLength);
106 }
107
108
109 #else
110
111 //this import workaround is to keep it a header-only library. and enums cannot be imported from the winapi.
112
113 extern "C"
114 {
115
116 typedef enum _JOBOBJECTINFOCLASS_
117 {
118 JobObjectBasicAccountingInformation_ = 1,
119 JobObjectBasicLimitInformation_,
120 JobObjectBasicProcessIdList_,
121 JobObjectBasicUIRestrictions_,
122 JobObjectSecurityLimitInformation_,
123 JobObjectEndOfJobTimeInformation_,
124 JobObjectAssociateCompletionPortInformation_,
125 JobObjectBasicAndIoAccountingInformation_,
126 JobObjectExtendedLimitInformation_,
127 JobObjectJobSetInformation_,
128 JobObjectGroupInformation_,
129 JobObjectNotificationLimitInformation_,
130 JobObjectLimitViolationInformation_,
131 JobObjectGroupInformationEx_,
132 JobObjectCpuRateControlInformation_,
133 JobObjectCompletionFilter_,
134 JobObjectCompletionCounter_,
135 JobObjectReserved1Information_ = 18,
136 JobObjectReserved2Information_,
137 JobObjectReserved3Information_,
138 JobObjectReserved4Information_,
139 JobObjectReserved5Information_,
140 JobObjectReserved6Information_,
141 JobObjectReserved7Information_,
142 JobObjectReserved8Information_,
143 MaxJobObjectInfoClass_
144 } JOBOBJECTINFOCLASS_;
145
146 typedef struct _JOBOBJECT_BASIC_LIMIT_INFORMATION_
147 {
148 ::boost::winapi::LARGE_INTEGER_ PerProcessUserTimeLimit;
149 ::boost::winapi::LARGE_INTEGER_ PerJobUserTimeLimit;
150 ::boost::winapi::DWORD_ LimitFlags;
151 ::boost::winapi::SIZE_T_ MinimumWorkingSetSize;
152 ::boost::winapi::SIZE_T_ MaximumWorkingSetSize;
153 ::boost::winapi::DWORD_ ActiveProcessLimit;
154 ::boost::winapi::ULONG_PTR_ Affinity;
155 ::boost::winapi::DWORD_ PriorityClass;
156 ::boost::winapi::DWORD_ SchedulingClass;
157 } JOBOBJECT_BASIC_LIMIT_INFORMATION_;
158
159
160 typedef struct _JOBOBJECT_BASIC_ACCOUNTING_INFORMATION_ {
161 ::boost::winapi::LARGE_INTEGER_ TotalUserTime;
162 ::boost::winapi::LARGE_INTEGER_ TotalKernelTime;
163 ::boost::winapi::LARGE_INTEGER_ ThisPeriodTotalUserTime;
164 ::boost::winapi::LARGE_INTEGER_ ThisPeriodTotalKernelTime;
165 ::boost::winapi::DWORD_ TotalPageFaultCount;
166 ::boost::winapi::DWORD_ TotalProcesses;
167 ::boost::winapi::DWORD_ ActiveProcesses;
168 ::boost::winapi::DWORD_ TotalTerminatedProcesses;
169 } JOBOBJECT_BASIC_ACCOUNTING_INFORMATION_;
170
171 typedef struct _IO_COUNTERS_
172 {
173 ::boost::winapi::ULONGLONG_ ReadOperationCount;
174 ::boost::winapi::ULONGLONG_ WriteOperationCount;
175 ::boost::winapi::ULONGLONG_ OtherOperationCount;
176 ::boost::winapi::ULONGLONG_ ReadTransferCount;
177 ::boost::winapi::ULONGLONG_ WriteTransferCount;
178 ::boost::winapi::ULONGLONG_ OtherTransferCount;
179 } IO_COUNTERS_;
180
181
182 typedef struct _JOBOBJECT_EXTENDED_LIMIT_INFORMATION_
183 {
184 JOBOBJECT_BASIC_LIMIT_INFORMATION_ BasicLimitInformation;
185 IO_COUNTERS_ IoInfo;
186 ::boost::winapi::SIZE_T_ ProcessMemoryLimit;
187 ::boost::winapi::SIZE_T_ JobMemoryLimit;
188 ::boost::winapi::SIZE_T_ PeakProcessMemoryUsed;
189 ::boost::winapi::SIZE_T_ PeakJobMemoryUsed;
190 } JOBOBJECT_EXTENDED_LIMIT_INFORMATION_;
191
192
193 /*BOOL WINAPI QueryInformationJobObject(
194 _In_opt_ HANDLE hJob,
195 _In_ JOBOBJECTINFOCLASS JobObjectInfoClass,
196 _Out_ LPVOID lpJobObjectInfo,
197 _In_ DWORD cbJobObjectInfoLength,
198 _Out_opt_ LPDWORD lpReturnLength
199 );
200 */
201 typedef ::boost::winapi::BOOL_ (BOOST_WINAPI_WINAPI_CC *query_information_job_object_p)(
202 ::boost::winapi::HANDLE_,
203 JOBOBJECTINFOCLASS_,
204 void *,
205 ::boost::winapi::DWORD_,
206 ::boost::winapi::DWORD_ *);
207
208
query_information_job_object(::boost::winapi::HANDLE_ hJob,JOBOBJECTINFOCLASS_ JobObjectInfoClass,void * lpJobObjectInfo,::boost::winapi::DWORD_ cbJobObjectInfoLength,::boost::winapi::DWORD_ * lpReturnLength)209 inline ::boost::winapi::BOOL_ query_information_job_object(
210 ::boost::winapi::HANDLE_ hJob,
211 JOBOBJECTINFOCLASS_ JobObjectInfoClass,
212 void *lpJobObjectInfo,
213 ::boost::winapi::DWORD_ cbJobObjectInfoLength,
214 ::boost::winapi::DWORD_ *lpReturnLength)
215 {
216 static ::boost::winapi::HMODULE_ h = ::boost::winapi::get_module_handle(
217 L"Kernel32.dll");
218 static query_information_job_object_p f = reinterpret_cast<query_information_job_object_p>(::boost::winapi::get_proc_address(
219 h, "QueryInformationJobObject"));
220
221 return (*f)(hJob, JobObjectInfoClass, lpJobObjectInfo,
222 cbJobObjectInfoLength, lpReturnLength);
223 }
224
225 /*BOOL WINAPI SetInformationJobObject(
226 _In_ HANDLE hJob,
227 _In_ JOBOBJECTINFOCLASS JobObjectInfoClass,
228 _In_ LPVOID lpJobObjectInfo,
229 _In_ DWORD cbJobObjectInfoLength
230 );*/
231
232 typedef ::boost::winapi::BOOL_ (BOOST_WINAPI_WINAPI_CC *set_information_job_object_p)(
233 ::boost::winapi::HANDLE_,
234 JOBOBJECTINFOCLASS_,
235 void *,
236 ::boost::winapi::DWORD_);
237
238 }
239
set_information_job_object(::boost::winapi::HANDLE_ hJob,JOBOBJECTINFOCLASS_ JobObjectInfoClass,void * lpJobObjectInfo,::boost::winapi::DWORD_ cbJobObjectInfoLength)240 inline ::boost::winapi::BOOL_ set_information_job_object(
241 ::boost::winapi::HANDLE_ hJob,
242 JOBOBJECTINFOCLASS_ JobObjectInfoClass,
243 void *lpJobObjectInfo,
244 ::boost::winapi::DWORD_ cbJobObjectInfoLength)
245 {
246 static ::boost::winapi::HMODULE_ h = ::boost::winapi::get_module_handle(
247 L"Kernel32.dll");
248 static set_information_job_object_p f = reinterpret_cast<set_information_job_object_p>(::boost::winapi::get_proc_address(
249 h, "SetInformationJobObject"));
250
251 return (*f)(hJob, JobObjectInfoClass, lpJobObjectInfo,
252 cbJobObjectInfoLength);
253 }
254
255 #endif
256
257 constexpr static ::boost::winapi::DWORD_ JOB_OBJECT_LIMIT_BREAKAWAY_OK_ = 0x00000800;
258
259 }}}}}
260
261 #endif /* BOOST_PROCESS_DETAIL_WINDOWS_JOB_WORKAROUND_HPP_ */
262