ReactOS 0.4.17-dev-806-gffa4164
job.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Core functions for managing Job Objects, a kernel mechanism
5 * for managing multiple processes as a single unit.
6 * COPYRIGHT: Copyright 2004-2012 Alex Ionescu (alex@relsoft.net) (stubs)
7 * Copyright 2004-2005 Thomas Weidenmueller <w3seek@reactos.com>
8 * Copyright 2015-2016 Samuel Serapión Vega <encoded@reactos.org>
9 * Copyright 2017 Mark Jansen <mark.jansen@reactos.org>
10 * Copyright 2018 Pierre Schweitzer <pierre@reactos.org>
11 * Copyright 2022 Timo Kreuzer <timo.kreuzer@reactos.org>
12 * Copyright 2024-2026 Gleb Surikov <glebs.surikovs@gmail.com>
13 */
14
15/* INCLUDES ******************************************************************/
16
17#include <ntoskrnl.h>
18#define NDEBUG
19#include <debug.h>
20
21/* GLOBALS *******************************************************************/
22
24
27
29
31{
32 1 * 6,
33 2 * 6,
34 3 * 6,
35 4 * 6,
36 5 * 6,
37 6 * 6,
38 7 * 6,
39 8 * 6,
40 9 * 6,
41 10 * 6
42};
43
45{
47
50
52
53 STANDARD_RIGHTS_ALL | THREAD_ALL_ACCESS // bug fixed only in vista
54};
55
57{
58 0x0,
68 0x4
69};
70
72{
73 0x0,
74 sizeof(ULONG),
75 sizeof(ULONG),
76 sizeof(ULONG),
77 sizeof(ULONG),
78 sizeof(ULONG),
79 sizeof(ULONG),
80 sizeof(HANDLE),
81 sizeof(ULONG),
82 sizeof(ULONG),
83 sizeof(ULONG)
84};
85
86/* DATA TYPE DEFINITIONS *****************************************************/
87
99{
103
117{
122
123/* FUNCTIONS *****************************************************************/
124
125CODE_SEG("INIT")
126VOID
127NTAPI
129{
132}
133
156static
159 _In_ PEJOB Job,
160 _In_opt_ PEPROCESS PreviousProcess
161)
162{
165
166 ASSERT(ExIsResourceAcquiredSharedLite(&Job->JobLock) != 0 ||
167 ExIsResourceAcquiredExclusiveLite(&Job->JobLock) != 0);
168
169 /* Check if we're already starting somewhere */
170 if (PreviousProcess != NULL)
171 {
172 ASSERT(PreviousProcess->Job == Job);
173 ASSERT(!IsListEmpty(&PreviousProcess->JobLinks));
174
175 /* Start where we left off */
176 Entry = PreviousProcess->JobLinks.Flink;
177 }
178 else
179 {
180 /* Start at the beginning */
181 Entry = Job->ProcessListHead.Flink;
182 }
183
184 /* Check if enumeration has completed */
185 if (Entry == &Job->ProcessListHead)
186 {
187 return NULL;
188 }
189
190 ASSERT(Entry->Flink != NULL);
191 ASSERT(Entry->Blink != NULL);
192 ASSERT(Entry->Flink->Blink == Entry);
193 ASSERT(Entry->Blink->Flink == Entry);
194
196 ASSERT(Process->Job == Job);
197 return Process;
198}
199
225static
228 _In_ PEJOB Job,
229 _In_opt_ PEPROCESS PreviousProcess
230)
231{
232 PEPROCESS Candidate;
233 PEPROCESS NextProcess = NULL;
234
236
237 Candidate = PreviousProcess;
238
239 while ((Candidate = PspGetNextProcessInJobLocked(Job, Candidate)) != NULL)
240 {
241 /*
242 * Skip processes whose deletion has begun. JobLinks remains valid
243 * while the job lock is held, allowing enumeration to continue.
244 */
245 if (ObReferenceObjectSafe(Candidate))
246 {
247 NextProcess = Candidate;
248 break;
249 }
250 }
251
253
254 /*
255 * This must occur after releasing the job lock. The dereference can invoke
256 * the process delete procedure, which removes JobLinks under the same lock.
257 */
258 if (PreviousProcess != NULL)
259 {
260 ObDereferenceObject(PreviousProcess);
261 }
262
263 return NextProcess;
264}
265
289NTAPI
291 _In_ PEJOB Job,
294)
295{
298
299 /* Iterate through all processes in the job */
301 Process != NULL;
303 {
305 if (!NT_SUCCESS(Status))
306 {
307 /*
308 * On successful iteration, PspGetNextProcessInJob consumes
309 * this reference. On failure, it must be released explicitly.
310 */
312 break;
313 }
314 }
315
316 return Status;
317}
318
345static
348 _In_ PEJOB Job,
351)
352{
355
356 ASSERT(ExIsResourceAcquiredSharedLite(&Job->JobLock) != 0 ||
357 ExIsResourceAcquiredExclusiveLite(&Job->JobLock) != 0);
358
359 /* Iterate through all processes in the job */
361 Process != NULL;
363 {
365 if (!NT_SUCCESS(Status))
366 break;
367 }
368
369 return Status;
370}
371
396NTAPI
398 _In_ PEJOB Job,
400 _In_opt_ PVOID CompletionValue,
401 _In_ BOOLEAN Quota
402)
403{
404 ASSERT(Job->CompletionPort != NULL);
405
406 ASSERT(ExIsResourceAcquiredSharedLite(&Job->JobLock) != 0 ||
407 ExIsResourceAcquiredExclusiveLite(&Job->JobLock) != 0);
408
409 return IoSetIoCompletion(Job->CompletionPort,
410 Job->CompletionKey,
411 CompletionValue,
413 Message,
414 Quota);
415}
416
431NTAPI
434 _In_ PEJOB Job
435)
436{
438 NTSTATUS CalloutStatus = STATUS_SUCCESS;
439 PVOID PreviousJob;
440
441 if (!ExAcquireRundownProtection(&Process->RundownProtect))
442 {
444 }
445
447
448 /* https://learn.microsoft.com/en-us/windows/win32/api/jobapi2/nf-jobapi2-assignprocesstojobobject:
449 "If the job or any of its parent jobs in the job chain is terminating
450 when AssignProcessToJob is called, the function fails" */
451 if (FlagOn(Job->JobFlags, PSP_JOB_TERMINATING))
452 {
454 goto Exit;
455 }
456
457 /* Prevent processes from being added to the job if it is flagged
458 for closing and has a limit on process termination on closing */
459 if (FlagOn(Job->LimitFlags, JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE) &&
460 FlagOn(Job->JobFlags, PSP_JOB_CLOSE_DONE))
461 {
463 goto Exit;
464 }
465
466 /* Check if the job has a limit on the number of active processes */
467 if (FlagOn(Job->LimitFlags, JOB_OBJECT_LIMIT_ACTIVE_PROCESS) &&
468 Job->ActiveProcesses >= Job->ActiveProcessLimit)
469 {
470 /* Check if job limit on active processes has been reached */
471 if (Job->CompletionPort)
472 {
473 /* If the job has a completion port, notify the job that the
474 limit on the number of active processes has been exceeded */
477 NULL,
478 TRUE);
479 }
480
482 goto Exit;
483 }
484
485 /* Acquire the reference owned by Process->Job before publishing the pointer.
486 This ensures that every observable non-NULL Process->Job is already
487 backed by its lifetime reference. If another assignment wins the race,
488 release the unused reference. */
490
491 /* JobLock protects the target job, but another caller may simultaneously
492 hold a different job's lock while trying to assign the same process */
494 Job,
495 NULL);
496 if (PreviousJob)
497 {
500 goto Exit;
501 }
502
503 /* Assignment is committed at this point. No subsequent structural
504 operation may fail.
505
506 Readers of Job->ProcessListHead are blocked by JobLock until the list
507 and counters are complete. */
508
509 ASSERT(IsListEmpty(&Process->JobLinks));
510
511 InsertTailList(&Job->ProcessListHead, &Process->JobLinks);
512
513 Job->TotalProcesses++;
514 Job->ActiveProcesses++;
515
516 if (Job->CompletionPort && Process->UniqueProcessId)
517 {
518 /* If the job has a completion port and the process has a unique ID,
519 notify the job of the new process */
522 Process->UniqueProcessId,
523 FALSE);
524 }
525
526 /* Hand the process to win32k, which enforces the UI restrictions. One
527 that has not connected to win32k yet is picked up when it does. */
528 if (Job->UIRestrictionsClass != 0 && Process->Win32Process != NULL)
529 {
530 CalloutStatus = PspInvokeW32JobCallout(Job,
532 Process->Win32Process);
533 }
534
535Exit:
537 ExReleaseRundownProtection(&Process->RundownProtect);
538
539 /* The assignment is committed, but win32k will not be enforcing the UI
540 restrictions, so the process must not run at all. The caller is told
541 the assignment failed, since that is what it asked for. */
542 if (!NT_SUCCESS(CalloutStatus))
543 {
544 DPRINT1("Failed to apply the UI restrictions of job %p to process %p: 0x%lx\n",
545 Job, Process, CalloutStatus);
546
547 (VOID)PsTerminateProcess(Process, CalloutStatus);
548 Status = CalloutStatus;
549 }
550
551 /* TODO: Ensure that job limits are respected */
552
553 return Status;
554}
555
572static
575 _In_ PEJOB Job,
577)
578{
579 ASSERT(Process->Job == Job);
580
581 ASSERT(ExIsResourceAcquiredExclusiveLite(&Job->JobLock) != 0);
582
584 {
585 return FALSE;
586 }
587
588 ASSERT(Job->ActiveProcesses != 0);
589
590 Job->ActiveProcesses--;
591
593
594 return Job->ActiveProcesses == 0;
595}
596
607VOID
608NTAPI
611)
612{
613 PEJOB Job;
614 BOOLEAN ActiveProcessZero;
615
616 Job = Process->Job;
617 ASSERT(Job != NULL);
618
620
621 ASSERT(Process->Job == Job);
622 ASSERT(Process->JobLinks.Flink != NULL);
623 ASSERT(Process->JobLinks.Blink != NULL);
624 ASSERT(!IsListEmpty(&Process->JobLinks));
625
626 /* Remove the process from the job's process list */
627 RemoveEntryList(&Process->JobLinks);
628 InitializeListHead(&Process->JobLinks);
629
630 /* Decrement the job's active process count if it is still active */
631 ActiveProcessZero = PspDeactivateProcessFromJobLocked(Job, Process);
632
633 /* TODO: Ensure that job limits are respected */
634
635 /* If no active processes remain, notify the job completion port */
636 if (ActiveProcessZero && Job->CompletionPort)
637 {
640 NULL,
641 FALSE);
642 }
643
645}
646
657VOID
658NTAPI
661)
662{
663 PEJOB Job;
664 BOOLEAN ActiveProcessZero;
665
666 Job = Process->Job;
667 ASSERT(Job != NULL);
668
670
671 /* Job membership is immutable in the current implementation */
672 ASSERT(Process->Job == Job);
673
674 /* Decrement the job's active process count if the process is still active */
675 ActiveProcessZero = PspDeactivateProcessFromJobLocked(Job, Process);
676
677 /* If no active processes remain, notify the job completion port */
678 if (ActiveProcessZero && Job->CompletionPort)
679 {
682 NULL,
683 FALSE);
684 }
685
686 /* TODO: Ensure that job limits are respected */
687
689}
690
708static
710NTAPI
714)
715{
717 BOOLEAN ActiveProcessZero;
719 PEJOB Job = TerminateContext->Job;
720 NTSTATUS ExitStatus = TerminateContext->ExitStatus;
721
722 ASSERT(Job != NULL);
723 ASSERT(Process->Job == Job);
724
725 /* Avoid entering process termination when the process has already
726 completed its active job transition */
728
730 {
731 goto Exit;
732 }
733
734 /* Terminate the process */
736
737 /* PsTerminateProcess can return STATUS_NOTHING_TO_TERMINATE
738 when it finds no threads (the ordinary process exit remains
739 responsible for completing job accounting in that case),
740 that should be treated as a no-op for job traversal */
741 if (!NT_SUCCESS(Status))
742 {
743 goto Exit;
744 }
745
746 /* Decrement the job's active process count if the process is still active */
747 ActiveProcessZero = PspDeactivateProcessFromJobLocked(Job, Process);
748
749 /* If there are no active processes left in the job, notify anyone waiting
750 for the job object by signaling completion */
751 if (ActiveProcessZero)
752 {
753 /* It is intended that the event is set to a signaled
754 state only in the termination path */
756
757 if (Job->CompletionPort)
758 {
761 NULL,
762 FALSE);
763 }
764 }
765
766Exit:
767
769
770 return STATUS_SUCCESS;
771}
772
787NTAPI
789 _In_ PEJOB Job,
791)
792{
796
798
799 /* Termination is idempotent, another caller already owns the traversal */
801 {
802 return STATUS_SUCCESS;
803 }
804
805 Context.Job = Job;
806 Context.ExitStatus = ExitStatus;
807
810 &Context);
811
812 /* The termination callback always returns STATUS_SUCCESS because
813 per-process termination failures are handled locally */
815
816 InterlockedAnd((PLONG)&Job->JobFlags, ~PSP_JOB_TERMINATING);
817
818 return Status;
819}
820
843VOID
844NTAPI
847 _In_ PVOID ObjectBody,
850 _In_ ULONG_PTR SystemHandleCount
851)
852{
854 PEJOB Job = (PEJOB)ObjectBody;
855 PVOID CompletionPort = NULL;
856
857 PAGED_CODE();
858
862
863 /* Proceed only when the last handle is left */
864 if (SystemHandleCount > 1)
865 {
866 DPRINT1("PspJobClose called with unexpected SystemHandleCount: %lu\n",
867 SystemHandleCount);
868 return;
869 }
870
871 /* Flag the job as closed */
873
875
876 /* If the job is set to kill on close, terminate all associated processes */
878 {
879 /* Keep the completion port associated during termination so that
880 final job messages can still be delivered */
882
885
887 }
888
889 CompletionPort = Job->CompletionPort;
890 Job->CompletionPort = NULL;
891 Job->CompletionKey = NULL;
892
894
895 if (CompletionPort)
896 {
897 ObDereferenceObject(CompletionPort);
898 }
899}
900
907VOID
908NTAPI
910{
911 PEJOB Job = (PEJOB)ObjectBody;
912
913 PAGED_CODE();
914
915 /* Let win32k tear down any per-job state it keeps for UI restrictions */
916 if (Job->UIRestrictionsClass != 0)
917 {
919 Job->UIRestrictionsClass = 0;
920 }
921
922 Job->LimitFlags = 0;
923
924 /* Remove the reference to the completion port if associated */
925 if (Job->CompletionPort)
926 {
928 Job->CompletionPort = NULL;
929 }
930
931 /* TODO: Ensure that job sets are respected */
932
933 /* Unlink the job object under lock */
935
936 ASSERT(!IsListEmpty(&Job->JobLinks));
938
940
941 /* TODO: Clean up security information */
942
943 /* Delete the resource associated with the job object */
945}
946
964static
967 _In_ PEJOB Job,
969 _In_ BOOLEAN IsExtendedLimit
970)
971{
973 ULONG AllowedFlags;
975
977
978 AllowedFlags = IsExtendedLimit
981
982 /* Validate flags */
983 if (ExtendedLimit->BasicLimitInformation.LimitFlags & ~AllowedFlags)
984 {
985 DPRINT1("Invalid LimitFlags specified: 0x%08X\n",
986 ExtendedLimit->BasicLimitInformation.LimitFlags & ~AllowedFlags);
988 }
989
990 if (ExtendedLimit->BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_PRESERVE_JOB_TIME &&
991 ExtendedLimit->BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_JOB_TIME)
992 {
993 DPRINT1("Invalid LimitFlags combination specified "
994 "(PRESERVE_JOB_TIME and JOB_TIME are mutually exclusive)\n");
996 }
997
998 /* Acquire the job lock */
999 ExAcquireResourceExclusiveLite(&Job->JobLock, TRUE);
1000
1001 /*
1002 * Basic Limits
1003 */
1004
1005 if (ExtendedLimit->BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_WORKINGSET)
1006 {
1007 /* https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-jobobject_basic_limit_information:
1008 "If MaximumWorkingSetSize is nonzero, MinimumWorkingSetSize cannot be zero"
1009 "If MinimumWorkingSetSize is nonzero, MaximumWorkingSetSize cannot be zero"
1010 Also check that the minimum doesn't exceed the maximum or both aren't equal to zero. */
1011 if ((ExtendedLimit->BasicLimitInformation.MaximumWorkingSetSize > 0 &&
1012 ExtendedLimit->BasicLimitInformation.MinimumWorkingSetSize <= 0)
1013 ||
1014 (ExtendedLimit->BasicLimitInformation.MinimumWorkingSetSize > 0 &&
1015 ExtendedLimit->BasicLimitInformation.MaximumWorkingSetSize <= 0)
1016 ||
1017 ExtendedLimit->BasicLimitInformation.MaximumWorkingSetSize <
1018 ExtendedLimit->BasicLimitInformation.MinimumWorkingSetSize)
1019 {
1021 goto ExitFromBasicLimits;
1022 }
1023
1024 Job->MinimumWorkingSetSize = ExtendedLimit->BasicLimitInformation.MinimumWorkingSetSize;
1025 Job->MaximumWorkingSetSize = ExtendedLimit->BasicLimitInformation.MaximumWorkingSetSize;
1026 }
1027
1028 if (ExtendedLimit->BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_PROCESS_TIME)
1029 {
1030 Job->PerProcessUserTimeLimit.QuadPart =
1031 ExtendedLimit->BasicLimitInformation.PerProcessUserTimeLimit.QuadPart;
1032 }
1033
1034 if (ExtendedLimit->BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_JOB_TIME)
1035 {
1036 Job->PerJobUserTimeLimit.QuadPart =
1037 ExtendedLimit->BasicLimitInformation.PerJobUserTimeLimit.QuadPart;
1038 }
1039
1040 if (ExtendedLimit->BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_ACTIVE_PROCESS)
1041 {
1042 Job->ActiveProcessLimit = ExtendedLimit->BasicLimitInformation.ActiveProcessLimit;
1043 }
1044
1045 if (ExtendedLimit->BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_AFFINITY)
1046 {
1047 /* https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-jobobject_basic_limit_information:
1048 "The affinity must be a subset of the system affinity mask obtained
1049 by calling the GetProcessAffinityMask function"
1050 The lpSystemAffinityMask obtained with GetProcessAffinityMask() corresponds
1051 to ActiveProcessorsAffinityMask, which in turn corresponds to KeActiveProcessors */
1052 if (ExtendedLimit->BasicLimitInformation.Affinity !=
1053 (ExtendedLimit->BasicLimitInformation.Affinity & KeActiveProcessors))
1054 {
1056 goto ExitFromBasicLimits;
1057 }
1058
1059 Job->Affinity = ExtendedLimit->BasicLimitInformation.Affinity;
1060 }
1061
1062 if (ExtendedLimit->BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_PRIORITY_CLASS)
1063 {
1064 if (ExtendedLimit->BasicLimitInformation.PriorityClass > PROCESS_PRIORITY_CLASS_ABOVE_NORMAL ||
1065 ExtendedLimit->BasicLimitInformation.PriorityClass <= PROCESS_PRIORITY_CLASS_INVALID)
1066 {
1068 goto ExitFromBasicLimits;
1069 }
1070
1071 /* https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-jobobject_basic_limit_information:
1072 "The calling process must enable the SE_INC_BASE_PRIORITY_NAME
1073 privilege" */
1075 Job,
1077 PreviousMode))
1078 {
1079 Job->PriorityClass = ExtendedLimit->BasicLimitInformation.PriorityClass;
1080 }
1081 else
1082 {
1084 goto ExitFromBasicLimits;
1085 }
1086 }
1087
1088 if (ExtendedLimit->BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_SCHEDULING_CLASS)
1089 {
1090 if (ExtendedLimit->BasicLimitInformation.SchedulingClass >= PSP_JOB_SCHEDULING_CLASSES)
1091 {
1093 goto ExitFromBasicLimits;
1094 }
1095
1096 /* https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-jobobject_basic_limit_information:
1097 "To use a scheduling class greater than 5, the calling process must
1098 enable the SE_INC_BASE_PRIORITY_NAME privilege" */
1099 if (ExtendedLimit->BasicLimitInformation.SchedulingClass > PSP_JOB_SCHEDULING_CLASS_DEFAULT)
1100 {
1102 Job,
1104 PreviousMode))
1105 {
1106 Job->SchedulingClass = ExtendedLimit->BasicLimitInformation.SchedulingClass;
1107 }
1108 else
1109 {
1111 goto ExitFromBasicLimits;
1112 }
1113 }
1114 else
1115 {
1116 Job->SchedulingClass = ExtendedLimit->BasicLimitInformation.SchedulingClass;
1117 }
1118 }
1119
1120 /*
1121 * Extended Memory Limits
1122 */
1123
1124 /* Acquire the memory limits lock */
1125 KeAcquireGuardedMutexUnsafe(&Job->MemoryLimitsLock);
1126
1127 if (ExtendedLimit->BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_PROCESS_MEMORY)
1128 {
1129 Job->ProcessMemoryLimit = ExtendedLimit->ProcessMemoryLimit >> PAGE_SHIFT;
1130 }
1131
1132 if (ExtendedLimit->BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_JOB_MEMORY)
1133 {
1134 Job->JobMemoryLimit = ExtendedLimit->JobMemoryLimit >> PAGE_SHIFT;
1135 }
1136
1137 /* Update the job's limit flags with the new ones. This includes dealing
1138 with those extended limits that only set some flag */
1139 Job->LimitFlags = ExtendedLimit->BasicLimitInformation.LimitFlags;
1140
1141
1142 /* Release locks */
1143
1144 KeReleaseGuardedMutexUnsafe(&Job->MemoryLimitsLock);
1145
1146ExitFromBasicLimits:
1147
1148 ExReleaseResourceLite(&Job->JobLock);
1149
1150 return Status;
1151}
1152
1171static
1173NTAPI
1177{
1178 PEJOB Job;
1179
1180 Job = (PEJOB)Context;
1181
1182 ASSERT(Process->Job == Job);
1183 ASSERT(Job->CompletionPort != NULL);
1184
1186
1187 /* Ensure the process is active and has a valid unique process ID */
1188 if (!FlagOn(Process->JobStatus, PSP_JOB_NOT_REALLY_ACTIVE) &&
1189 Process->UniqueProcessId)
1190 {
1193 Process->UniqueProcessId,
1194 FALSE);
1195 }
1196
1197 return STATUS_SUCCESS;
1198}
1199
1221static
1224 _In_ PEJOB Job,
1226)
1227{
1231
1233
1234 if (!AssociateCpInfo->CompletionPort)
1235 {
1237 }
1238
1239 Status = ObReferenceObjectByHandle(AssociateCpInfo->CompletionPort,
1243 &IoCompletion,
1244 NULL);
1245 if (!NT_SUCCESS(Status))
1246 {
1247 return Status;
1248 }
1249
1250 ExAcquireResourceExclusiveLite(&Job->JobLock, TRUE);
1251
1252 /* Check if the job already has a completion port or is in a final state */
1253 if (Job->CompletionPort || FlagOn(Job->JobFlags, PSP_JOB_CLOSE_DONE))
1254 {
1255 ExReleaseResourceLite(&Job->JobLock);
1258 }
1259
1260 Job->CompletionKey = AssociateCpInfo->CompletionKey;
1261 Job->CompletionPort = IoCompletion;
1262
1263 /* Inform all processes in the job about the association
1264 N.B. Assignment is serialized by JobLock; a process is therefore covered
1265 either by this enumeration or by the normal assignment path */
1268 Job);
1269
1271
1272 ExReleaseResourceLite(&Job->JobLock);
1273
1274 /* The completion port association is committed at this point. Initial process
1275 notifications are best-effort and a failure to queue one must not turn
1276 a successful association into a failure. */
1277 return STATUS_SUCCESS;
1278}
1279
1295static
1298 _In_ PEJOB Job,
1300)
1301{
1302 PLIST_ENTRY NextEntry;
1303 PROCESS_VALUES Values;
1304
1305 /* Zero the basic accounting information */
1306 RtlZeroMemory(&BasicAndIo->BasicInfo, sizeof(BasicAndIo->BasicInfo));
1307
1308 /* Lock the job object */
1310
1311 /* Initialize with job's accumulated accounting data */
1312 BasicAndIo->BasicInfo.TotalUserTime.QuadPart = Job->TotalUserTime.QuadPart;
1313 BasicAndIo->BasicInfo.TotalKernelTime.QuadPart = Job->TotalKernelTime.QuadPart;
1314 BasicAndIo->BasicInfo.ThisPeriodTotalUserTime.QuadPart = Job->ThisPeriodTotalUserTime.QuadPart;
1315 BasicAndIo->BasicInfo.ThisPeriodTotalKernelTime.QuadPart = Job->ThisPeriodTotalKernelTime.QuadPart;
1316 BasicAndIo->BasicInfo.TotalPageFaultCount = Job->TotalPageFaultCount;
1317 BasicAndIo->BasicInfo.TotalProcesses = Job->TotalProcesses;
1318 BasicAndIo->BasicInfo.ActiveProcesses = Job->ActiveProcesses;
1319 BasicAndIo->BasicInfo.TotalTerminatedProcesses = Job->TotalTerminatedProcesses;
1320
1321 /* Set I/O info (even though it may not be returned in some cases) */
1322 BasicAndIo->IoInfo.ReadOperationCount = Job->ReadOperationCount;
1323 BasicAndIo->IoInfo.WriteOperationCount = Job->WriteOperationCount;
1324 BasicAndIo->IoInfo.OtherOperationCount = Job->OtherOperationCount;
1325 BasicAndIo->IoInfo.ReadTransferCount = Job->ReadTransferCount;
1326 BasicAndIo->IoInfo.WriteTransferCount = Job->WriteTransferCount;
1327 BasicAndIo->IoInfo.OtherTransferCount = Job->OtherTransferCount;
1328
1329 /* Sum up accounting data for each active process in the job */
1330 for (NextEntry = Job->ProcessListHead.Flink;
1331 NextEntry != &Job->ProcessListHead;
1332 NextEntry = NextEntry->Flink)
1333 {
1334 PEPROCESS Process = CONTAINING_RECORD(NextEntry, EPROCESS, JobLinks);
1335
1336 /* Skip folded accounting processes */
1337 if (!FlagOn(Process->JobStatus, PSP_JOB_ACCOUNTING_FOLDED))
1338 {
1339 KeQueryValuesProcess(&Process->Pcb, &Values);
1340
1341 /* Accumulate user and kernel times, and I/O counts */
1342 BasicAndIo->BasicInfo.TotalUserTime.QuadPart += Values.TotalUserTime.QuadPart;
1343 BasicAndIo->BasicInfo.TotalKernelTime.QuadPart += Values.TotalKernelTime.QuadPart;
1344 BasicAndIo->IoInfo.ReadOperationCount += Values.IoInfo.ReadOperationCount;
1345 BasicAndIo->IoInfo.WriteOperationCount += Values.IoInfo.WriteOperationCount;
1346 BasicAndIo->IoInfo.OtherOperationCount += Values.IoInfo.OtherOperationCount;
1347 BasicAndIo->IoInfo.ReadTransferCount += Values.IoInfo.ReadTransferCount;
1348 BasicAndIo->IoInfo.WriteTransferCount += Values.IoInfo.WriteTransferCount;
1349 BasicAndIo->IoInfo.OtherTransferCount += Values.IoInfo.OtherTransferCount;
1350 }
1351 }
1352
1353 /* Release the job lock */
1355
1356 return STATUS_SUCCESS;
1357}
1358
1377static
1380 _In_ PEJOB Job,
1381 _In_ BOOLEAN Extended,
1383)
1384{
1385 PKTHREAD CurrentThread = KeGetCurrentThread();
1386
1387 /* Lock the job object */
1388 KeEnterGuardedRegionThread(CurrentThread);
1389 ExAcquireResourceSharedLite(&Job->JobLock, TRUE);
1390
1391 /* Copy basic limit information */
1392 ExtendedLimit->BasicLimitInformation.LimitFlags = Job->LimitFlags;
1393 ExtendedLimit->BasicLimitInformation.MinimumWorkingSetSize = Job->MinimumWorkingSetSize;
1394 ExtendedLimit->BasicLimitInformation.MaximumWorkingSetSize = Job->MaximumWorkingSetSize;
1395 ExtendedLimit->BasicLimitInformation.ActiveProcessLimit = Job->ActiveProcessLimit;
1396 ExtendedLimit->BasicLimitInformation.PriorityClass = Job->PriorityClass;
1397 ExtendedLimit->BasicLimitInformation.SchedulingClass = Job->SchedulingClass;
1398 ExtendedLimit->BasicLimitInformation.Affinity = Job->Affinity;
1399 ExtendedLimit->BasicLimitInformation.PerProcessUserTimeLimit.QuadPart = Job->PerProcessUserTimeLimit.QuadPart;
1400 ExtendedLimit->BasicLimitInformation.PerJobUserTimeLimit.QuadPart = Job->PerJobUserTimeLimit.QuadPart;
1401
1402 /* If extended limits are requested, include memory limits */
1403 if (Extended)
1404 {
1405 KeAcquireGuardedMutexUnsafe(&Job->MemoryLimitsLock);
1406
1407 ExtendedLimit->ProcessMemoryLimit = Job->ProcessMemoryLimit << PAGE_SHIFT;
1408 ExtendedLimit->JobMemoryLimit = Job->JobMemoryLimit << PAGE_SHIFT;
1409 ExtendedLimit->PeakProcessMemoryUsed = Job->PeakProcessMemoryUsed << PAGE_SHIFT;
1410 ExtendedLimit->PeakJobMemoryUsed = Job->PeakJobMemoryUsed << PAGE_SHIFT;
1411
1412 KeReleaseGuardedMutexUnsafe(&Job->MemoryLimitsLock);
1413
1414 /* Zero out IoInfo to avoid kernel memory leaks */
1415 RtlZeroMemory(&ExtendedLimit->IoInfo, sizeof(ExtendedLimit->IoInfo));
1416 }
1417
1418 /* Release the job lock */
1419 ExReleaseResourceLite(&Job->JobLock);
1420 KeLeaveGuardedRegionThread(CurrentThread);
1421
1422 return STATUS_SUCCESS;
1423}
1424
1442static
1444NTAPI
1448)
1449{
1451
1452 /* Skip processes that are not really active */
1453 if (FlagOn(Process->JobStatus, PSP_JOB_NOT_REALLY_ACTIVE))
1454 {
1455 /* Continue to the next process */
1456 return STATUS_SUCCESS;
1457 }
1458
1459 /* An active process may be linked before its process identifier has been
1460 assigned - such a process is not representable in this information class */
1461 if (Process->UniqueProcessId == NULL)
1462 {
1463 ASSERT(QueryContext->ProcessIdList->NumberOfAssignedProcesses != 0);
1464
1466
1467 return STATUS_SUCCESS;
1468 }
1469
1470 if (QueryContext->RemainingLength < sizeof(ULONG_PTR))
1471 {
1473 }
1474
1475 *QueryContext->NextProcessId++ = (ULONG_PTR)Process->UniqueProcessId;
1476
1477 QueryContext->RemainingLength -= sizeof(ULONG_PTR);
1478
1479 QueryContext->ProcessIdList->NumberOfProcessIdsInList++;
1480
1481 return STATUS_SUCCESS;
1482}
1483
1508static
1511 _In_ PEJOB Job,
1512 _Out_writes_bytes_(JobInformationLength) PJOBOBJECT_BASIC_PROCESS_ID_LIST ProcIdList,
1513 _In_ ULONG JobInformationLength,
1514 _Out_ PULONG ReturnRequiredLength
1515)
1516{
1519
1520 /* Check if the buffer provided is large enough to hold at least the
1521 fixed portion of JOBOBJECT_BASIC_PROCESS_ID_LIST */
1522 if (JobInformationLength < sizeof(JOBOBJECT_BASIC_PROCESS_ID_LIST))
1523 {
1525 }
1526
1527 QueryContext.ProcessIdList = ProcIdList;
1528 QueryContext.NextProcessId = &ProcIdList->ProcessIdList[0];
1529 QueryContext.RemainingLength = JobInformationLength - FIELD_OFFSET(JOBOBJECT_BASIC_PROCESS_ID_LIST,
1530 ProcessIdList);
1531
1533
1535
1536 _SEH2_TRY
1537 {
1538 ProcIdList->NumberOfAssignedProcesses = Job->ActiveProcesses;
1539 ProcIdList->NumberOfProcessIdsInList = 0;
1540
1543 &QueryContext);
1544 }
1546 {
1548 }
1549 _SEH2_END;
1550
1552
1554 {
1555 /* Report the bytes actually written */
1556 *ReturnRequiredLength = (ULONG)(JobInformationLength - QueryContext.RemainingLength);
1557 }
1558 else
1559 {
1560 *ReturnRequiredLength = 0;
1561 }
1562
1563 return Status;
1564}
1565
1566/*
1567 * @implemented
1568 */
1569PVOID
1570NTAPI
1572{
1573 ASSERT(Job);
1574 return (PVOID)&Job->JobLock;
1575}
1576
1577/*
1578 * @implemented
1579 */
1580ULONG
1581NTAPI
1583{
1584 ASSERT(Job);
1585 return Job->SessionId;
1586}
1587
1588/*
1589 * @implemented
1590 */
1591ULONG
1592NTAPI
1594{
1595 ASSERT(Job);
1596 return Job->UIRestrictionsClass;
1597}
1598
1599/*
1600 * @implemented
1601 */
1602VOID
1603NTAPI
1605 PEJOB Job,
1606 ULONG UIRestrictionsClass
1607)
1608{
1609 ASSERT(Job);
1610 (void)InterlockedExchangeUL(&Job->UIRestrictionsClass, UIRestrictionsClass);
1611}
1612
1636NTAPI
1638 _In_ PEJOB Job,
1639 _In_ PSW32JOBCALLOUTTYPE CalloutType,
1641)
1642{
1644
1645 /* Nothing to do if win32k has not registered a callout */
1646 if (PspW32JobCallout == NULL)
1647 {
1648 return STATUS_SUCCESS;
1649 }
1650
1651 Parameters.Job = Job;
1652 Parameters.CalloutType = CalloutType;
1653 Parameters.Data = Data;
1654
1656}
1657
1676static
1679 _In_ PEJOB Job,
1680 _In_ ULONG UIRestrictionsClass
1681)
1682{
1684
1685 /* Reject restrictions we do not know about */
1686 if (UIRestrictionsClass & ~JOB_OBJECT_UILIMIT_ALL)
1687 {
1689 }
1690
1692
1693 /* Only bother win32k if something actually changes */
1694 if (Job->UIRestrictionsClass != UIRestrictionsClass)
1695 {
1698 UlongToPtr(UIRestrictionsClass));
1699 if (NT_SUCCESS(Status))
1700 {
1701 Job->UIRestrictionsClass = UIRestrictionsClass;
1702 }
1703 }
1704
1706
1707 return Status;
1708}
1709
1727NTAPI
1729 _Out_ PHANDLE JobHandle,
1732)
1733{
1734 HANDLE Handle;
1735 PEJOB Job;
1737 PEPROCESS CurrentProcess;
1739
1740 PAGED_CODE();
1741
1743 CurrentProcess = PsGetCurrentProcess();
1744
1745 /* Check for valid buffers */
1746 if (PreviousMode != KernelMode)
1747 {
1748 _SEH2_TRY
1749 {
1750 ProbeForWriteHandle(JobHandle);
1751 }
1753 {
1754 return _SEH2_GetExceptionCode();
1755 }
1756 _SEH2_END;
1757 }
1758
1759 /* Create the job object */
1761 PsJobType,
1764 NULL,
1765 sizeof(EJOB),
1766 0,
1767 0,
1768 (PVOID *)&Job);
1769
1770 if (!NT_SUCCESS(Status))
1771 {
1772 DPRINT1("Failed to create job object, Status 0x%08lx\n", Status);
1773 return Status;
1774 }
1775
1776 /* Initialize the job object */
1777
1778 RtlZeroMemory(Job, sizeof(*Job));
1779
1782
1783 /* Make sure that early destruction doesn't attempt to remove
1784 the object from the list before it even gets added */
1786
1787 /* Inherit the session ID from the caller */
1788 Job->SessionId = PsGetProcessSessionId(CurrentProcess);
1789
1790 /* Initialize the job limits lock */
1792
1793 /* Initialize the job lock */
1795
1796 /* Initialize the event object within the job */
1798
1799 /* Set the scheduling class */
1801
1802 /* Link the object into the global job list */
1806
1807 /* Insert the job object into the object table */
1808 Status = ObInsertObject(Job,
1809 NULL,
1811 0,
1812 NULL,
1813 &Handle);
1814
1815 if (NT_SUCCESS(Status))
1816 {
1817 /* Pass the handle back to the caller */
1818 _SEH2_TRY
1819 {
1820 *JobHandle = Handle;
1821 }
1823 {
1825 }
1826 _SEH2_END;
1827 }
1828
1829 return Status;
1830}
1831
1833NTAPI
1835 IN PJOB_SET_ARRAY UserJobSet,
1836 IN ULONG Flags)
1837{
1840}
1841
1861NTAPI
1863 _Out_ PHANDLE JobHandle,
1866)
1867{
1869 HANDLE Handle;
1871
1872 PAGED_CODE();
1873
1875
1876 /* Check for valid buffers */
1877 if (PreviousMode != KernelMode)
1878 {
1879 _SEH2_TRY
1880 {
1881 ProbeForWriteHandle(JobHandle);
1882 }
1884 {
1886 }
1887 _SEH2_END;
1888 }
1889
1891 PsJobType,
1893 NULL,
1895 NULL,
1896 &Handle);
1897 if (NT_SUCCESS(Status))
1898 {
1899 _SEH2_TRY
1900 {
1901 *JobHandle = Handle;
1902 }
1904 {
1906 }
1907 _SEH2_END;
1908 }
1909
1910 return Status;
1911}
1912
1927NTAPI
1929 _In_ HANDLE JobHandle,
1931)
1932{
1934 PEJOB Job;
1938
1939 PAGED_CODE();
1940
1942
1943 /* Reference the job. JOB_OBJECT_ASSIGN_PROCESS rights are required
1944 for assignment */
1947 PsJobType,
1949 (PVOID *)&Job,
1950 NULL);
1951 if (!NT_SUCCESS(Status))
1952 {
1953 return Status;
1954 }
1955
1956 /* Reference the process. The handle must have the PROCESS_SET_QUOTA and
1957 PROCESS_TERMINATE access rights. */
1962 (PVOID *)&Process,
1963 NULL);
1964 if (!NT_SUCCESS(Status))
1965 {
1967 return Status;
1968 }
1969
1970 /* Get the session ID - it must match the process and the job creator */
1972
1973 if (Process->Job != NULL || SessionId != Job->SessionId)
1974 {
1975 /* Return STATUS_ACCESS_DENIED if the process is already assigned
1976 to a job or the session ID is different */
1979 return STATUS_ACCESS_DENIED;
1980 }
1981
1983
1985 {
1986 /* Preserve the assignment failure */
1988 }
1989
1992
1993 return Status;
1994}
1995
2013NTAPI
2016 _In_opt_ HANDLE JobHandle
2017)
2018{
2021 PEJOB ProcessJob;
2022 PEJOB JobObjectFromHandle;
2024
2026
2027 PAGED_CODE();
2028
2029 /* Check if the process handle is the current process */
2031 {
2032 /* If so, directly use the current process object */
2034 }
2035 else
2036 {
2037 /* Reference the process object by handle */
2042 (PVOID *)&Process,
2043 NULL);
2044 if (!NT_SUCCESS(Status))
2045 {
2046 return Status;
2047 }
2048 }
2049
2050 /* Get the job object associated with the process */
2051 ProcessJob = Process->Job;
2052
2053 if (ProcessJob != NULL)
2054 {
2055 /* If no specific job handle is provided,
2056 the process is assigned to a job */
2057 if (JobHandle == NULL)
2058 {
2060 }
2061 else
2062 {
2063 /* Get the job object from the provided job handle
2064 and compare it with the process job */
2067 PsJobType,
2069 (PVOID *)&JobObjectFromHandle,
2070 NULL);
2071 if (NT_SUCCESS(Status))
2072 {
2073 /* Compare the job objects */
2074 if ((ProcessJob == JobObjectFromHandle))
2075 {
2077 }
2078 else
2079 {
2081 }
2082
2083 /* Dereference the job object handle */
2084 ObDereferenceObject(JobObjectFromHandle);
2085 }
2086 }
2087 }
2088 else
2089 {
2090 /* The process is not assigned to any job */
2092 }
2093
2094 /* Dereference the process object if it was referenced */
2096 {
2098 }
2099
2100 return Status;
2101}
2102
2117NTAPI
2119 _In_ HANDLE JobHandle,
2121)
2122{
2124 PEJOB Job;
2126
2127 PAGED_CODE();
2128
2130
2133 PsJobType,
2135 (PVOID *)&Job,
2136 NULL);
2137 if (NT_SUCCESS(Status))
2138 {
2141 }
2142
2143 return Status;
2144}
2145
2178NTAPI
2180 _In_opt_ HANDLE JobHandle,
2181 _In_ JOBOBJECTINFOCLASS JobInformationClass,
2182 _Out_writes_bytes_(JobInformationLength) PVOID JobInformation,
2183 _In_ ULONG JobInformationLength,
2185)
2186{
2187 PEJOB Job;
2189 BOOLEAN NoOutput;
2190 PVOID JobInfoBuffer;
2191 PKTHREAD CurrentThread;
2195 JOBOBJECT_BASIC_UI_RESTRICTIONS UiRestrictions;
2196 ULONG RequiredLength, RequiredAlign, ReturnRequiredLength;
2197
2198 PAGED_CODE();
2199
2200 CurrentThread = KeGetCurrentThread();
2201
2202 /* Validate that JobInformationClass is in the expected range */
2203 if (JobInformationClass > JobObjectJobSetInformation ||
2204 JobInformationClass < JobObjectBasicAccountingInformation)
2205 {
2207 }
2208
2209 /* Determine the required length and alignment for the class */
2210 RequiredLength = PspJobInfoLengths[JobInformationClass];
2211 RequiredAlign = PspJobInfoAlign[JobInformationClass];
2212 ReturnRequiredLength = RequiredLength;
2213
2214 /* If length mismatch (needed versus provided) */
2215 if (JobInformationLength != RequiredLength)
2216 {
2217 /* This can only be accepted if the class is variable length
2218 (JobObjectBasicProcessIdList or JobObjectSecurityLimitInformation) or
2219 if size is bigger than needed */
2220 if ((JobInformationClass != JobObjectBasicProcessIdList &&
2221 JobInformationClass != JobObjectSecurityLimitInformation) ||
2222 JobInformationLength < RequiredLength)
2223 {
2225 }
2226
2227 /* Set what we need to copy out */
2228 RequiredLength = JobInformationLength;
2229 }
2230
2232
2233 /* If the request is coming from user mode, probe the user buffer */
2234 if (PreviousMode != KernelMode)
2235 {
2236 ASSERT(RequiredAlign == 1 ||
2237 RequiredAlign == 2 ||
2238 RequiredAlign == 4 ||
2239 RequiredAlign == 8 ||
2240 RequiredAlign == 16);
2241
2242 _SEH2_TRY
2243 {
2244 /* Probe the buffer */
2245 if (JobInformation != NULL)
2246 {
2247 ProbeForWrite(JobInformation, JobInformationLength, RequiredAlign);
2248 }
2249
2250 /* Probe the return length if required */
2251 if (ReturnLength != NULL)
2252 {
2254 }
2255 }
2257 {
2259 }
2260 _SEH2_END;
2261 }
2262
2263 /* If a job handle was provided, use it */
2264 if (JobHandle != NULL)
2265 {
2268 PsJobType,
2270 (PVOID *)&Job,
2271 NULL);
2272 if (!NT_SUCCESS(Status))
2273 {
2274 return Status;
2275 }
2276 }
2277 /* Otherwise, get our current process' job, if any */
2278 else
2279 {
2280 PEPROCESS CurrentProcess;
2281
2282 CurrentProcess = (PEPROCESS)CurrentThread->ApcState.Process;
2283 Job = CurrentProcess->Job;
2284 if (Job == NULL)
2285 {
2286 return STATUS_ACCESS_DENIED;
2287 }
2288
2289 ObReferenceObject(Job);
2290 }
2291
2292 /* By default, assume we'll have to copy data */
2293 NoOutput = FALSE;
2294
2295 switch (JobInformationClass)
2296 {
2299 {
2300 Status = PspQueryJobBasicAccountingInfo(Job, &BasicAndIo);
2301 JobInfoBuffer = &BasicAndIo;
2302 break;
2303 }
2306 {
2308 JobInformationClass == JobObjectExtendedLimitInformation,
2309 &ExtendedLimit);
2310 JobInfoBuffer = &ExtendedLimit;
2311 break;
2312 }
2314 {
2316 (PJOBOBJECT_BASIC_PROCESS_ID_LIST)JobInformation,
2317 JobInformationLength,
2318 &ReturnRequiredLength);
2319
2320 /* No need to copy data as it's directly filled in the helper */
2321 NoOutput = TRUE;
2322 break;
2323 }
2325 {
2326 UiRestrictions.UIRestrictionsClass = Job->UIRestrictionsClass;
2327 JobInfoBuffer = &UiRestrictions;
2328 break;
2329 }
2334 DPRINT1("Class %d not implemented\n", JobInformationClass);
2336 break;
2338 default:
2339 DPRINT1("Invalid class %d\n", JobInformationClass);
2341 break;
2342 }
2343
2344 /* Job is no longer required */
2346
2347 /* If we succeeded, copy back data */
2348 if (NT_SUCCESS(Status))
2349 {
2350 _SEH2_TRY
2351 {
2352 /* If we have anything to copy, do it */
2353 if (!NoOutput)
2354 {
2355 RtlCopyMemory(JobInformation, JobInfoBuffer, RequiredLength);
2356 }
2357
2358 /* And return length if asked */
2359 if (ReturnLength != NULL)
2360 {
2361 *ReturnLength = ReturnRequiredLength;
2362 }
2363 }
2365 {
2367 }
2368 _SEH2_END;
2369 }
2370
2371 return Status;
2372}
2373
2405NTAPI
2407 _In_ HANDLE JobHandle,
2408 _In_ JOBOBJECTINFOCLASS JobInformationClass,
2409 _In_reads_bytes_(JobInformationLength) PVOID JobInformation,
2410 _In_ ULONG JobInformationLength
2411)
2412{
2413 PEJOB Job;
2415 PKTHREAD CurrentThread;
2418 ULONG RequiredLength, RequiredAlign;
2419
2420 PAGED_CODE();
2421
2422 CurrentThread = KeGetCurrentThread();
2423
2424 /* Validate that JobInformationClass is in the expected range */
2425 if (JobInformationClass > JobObjectJobSetInformation ||
2426 JobInformationClass < JobObjectBasicAccountingInformation)
2427 {
2429 }
2430
2431 /* Determine the required length and alignment for the class */
2432 RequiredLength = PspJobInfoLengths[JobInformationClass];
2433 RequiredAlign = PspJobInfoAlign[JobInformationClass];
2434
2436
2437 /* If the request is coming from user mode, probe the user buffer */
2438 if (PreviousMode != KernelMode)
2439 {
2440 ASSERT(RequiredAlign == 1 ||
2441 RequiredAlign == 2 ||
2442 RequiredAlign == 4 ||
2443 RequiredAlign == 8 ||
2444 RequiredAlign == 16);
2445
2446 _SEH2_TRY
2447 {
2448 /* Probe out buffer for read */
2449 if (JobInformationLength != 0)
2450 {
2451 ProbeForRead(JobInformation, JobInformationLength, RequiredAlign);
2452 }
2453 }
2455 {
2457 }
2458 _SEH2_END;
2459 }
2460
2461 /* Validate that the provided buffer length matches the expected size
2462 for the class */
2463 if (JobInformationLength != RequiredLength)
2464 {
2466 }
2467
2469
2470 /* If setting security limits, additional security access rights
2471 are required */
2472 if (JobInformationClass == JobObjectSecurityLimitInformation)
2473 {
2475 }
2476
2479 PsJobType,
2481 (PVOID *)&Job,
2482 NULL);
2483 if (!NT_SUCCESS(Status))
2484 {
2485 return Status;
2486 }
2487
2488 /* And set the information.
2489 *
2490 * N.B. Disable APC delivery for the set operation. The handlers below may
2491 * acquire locks using unsafe variants which expect the caller to have
2492 * already established this state.
2493 */
2494
2495 KeEnterGuardedRegionThread(CurrentThread);
2496
2497 switch (JobInformationClass)
2498 {
2501 {
2503 BOOLEAN IsExtendedLimit = JobInformationClass == JobObjectExtendedLimitInformation;
2504
2505 _SEH2_TRY
2506 {
2507 /* If asking for extending limits */
2508 if (IsExtendedLimit)
2509 {
2510 ExtendedLimit = *(PJOBOBJECT_EXTENDED_LIMIT_INFORMATION)JobInformation;
2511 }
2512 else
2513 {
2514 RtlZeroMemory(&ExtendedLimit, sizeof(ExtendedLimit));
2515 ExtendedLimit.BasicLimitInformation =
2516 *(PJOBOBJECT_BASIC_LIMIT_INFORMATION)JobInformation;
2517 }
2518 }
2520 {
2522 goto Exit;
2523 }
2524 _SEH2_END;
2525
2527 &ExtendedLimit,
2528 IsExtendedLimit);
2529 goto Exit;
2530 }
2532 {
2534
2535 _SEH2_TRY
2536 {
2537 RtlCopyMemory(&AssociateCpInfo,
2538 JobInformation,
2539 sizeof(AssociateCpInfo));
2540 }
2542 {
2544 break;
2545 }
2546 _SEH2_END;
2547
2548 Status = PspAssociateCompletionPortWithJob(Job, &AssociateCpInfo);
2549 break;
2550 }
2552 {
2553 JOBOBJECT_BASIC_UI_RESTRICTIONS UiRestrictions;
2554
2555 _SEH2_TRY
2556 {
2557 UiRestrictions = *(PJOBOBJECT_BASIC_UI_RESTRICTIONS)JobInformation;
2558 }
2560 {
2562 goto Exit;
2563 }
2564 _SEH2_END;
2565
2566 Status = PspSetJobUIRestrictions(Job, UiRestrictions.UIRestrictionsClass);
2567 break;
2568 }
2575 DPRINT1("Class %d not implemented\n", JobInformationClass);
2577 break;
2579 default:
2580 DPRINT1("Invalid class %d\n", JobInformationClass);
2582 break;
2583 }
2584
2585Exit:
2586 KeLeaveGuardedRegionThread(CurrentThread);
2587
2589
2590 return Status;
2591}
2592
2593/* EOF */
#define PAGED_CODE()
#define CODE_SEG(...)
#define STATUS_PRIVILEGE_NOT_HELD
Definition: DriverTester.h:9
_In_ PVOID _In_ ULONG _Out_ PVOID _In_ ULONG _Inout_ PULONG ReturnLength
_In_ PVOID _In_ ULONG _Out_ PVOID _In_ ULONG _Inout_ PULONG _In_ KPROCESSOR_MODE PreviousMode
#define VOID
Definition: acefi.h:82
unsigned char BOOLEAN
Definition: actypes.h:127
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
#define UNIMPLEMENTED
Definition: ntoskrnl.c:15
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42
_In_ HANDLE _In_ CONST PDXGKMDT_OPM_GET_INFO_PARAMETERS Parameters
Definition: dispmprt.h:321
_In_ ULONG _In_ ULONG _In_opt_ DXGKCB_MIRACAST_SEND_MESSAGE_CALLBACK Callback
Definition: dispmprt.h:620
_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID _In_ ULONG _In_ ULONG Flags
Definition: dispmprt.h:245
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
ULONG SessionId
Definition: dllmain.c:28
static const WCHAR Message[]
Definition: register.c:74
#define UlongToPtr(u)
Definition: config.h:106
#define ULONG_PTR
Definition: config.h:101
NTSTATUS NTAPI IoCompletion(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Ctx)
Definition: control.c:393
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define ExAcquireResourceExclusiveLite(res, wait)
Definition: env_spec_w32.h:615
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define ExAcquireResourceSharedLite(res, wait)
Definition: env_spec_w32.h:621
#define ExReleaseRundownProtection
Definition: ex.h:139
#define ExGetPreviousMode
Definition: ex.h:143
#define InterlockedExchangeUL(Target, Value)
Definition: ex.h:1547
#define ExAcquireRundownProtection
Definition: ex.h:138
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
ULONG Handle
Definition: gdb_input.c:15
Status
Definition: gdiplustypes.h:24
VOID FASTCALL KeReleaseGuardedMutexUnsafe(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:75
VOID FASTCALL KeInitializeGuardedMutex(OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:31
VOID FASTCALL KeAcquireGuardedMutexUnsafe(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:64
VOID FASTCALL ExAcquireFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:23
VOID FASTCALL ExReleaseFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:31
#define KeGetCurrentThread
Definition: hal.h:55
#define JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO
Definition: pstypes.h:252
#define JOB_OBJECT_UILIMIT_ALL
Definition: pstypes.h:235
#define PROCESS_TERMINATE
Definition: pstypes.h:153
#define JOB_OBJECT_SET_SECURITY_ATTRIBUTES
Definition: pstypes.h:200
#define PROCESS_QUERY_INFORMATION
Definition: pstypes.h:162
#define JOB_OBJECT_LIMIT_PRESERVE_JOB_TIME
Definition: pstypes.h:214
#define PROCESS_PRIORITY_CLASS_INVALID
Definition: pstypes.h:102
#define JOB_OBJECT_MSG_ACTIVE_PROCESS_LIMIT
Definition: pstypes.h:251
struct _JOBOBJECT_BASIC_PROCESS_ID_LIST JOBOBJECT_BASIC_PROCESS_ID_LIST
#define JOB_OBJECT_LIMIT_JOB_MEMORY
Definition: pstypes.h:217
@ PsW32JobCalloutTerminate
Definition: pstypes.h:555
@ PsW32JobCalloutAddProcess
Definition: pstypes.h:554
@ PsW32JobCalloutSetInformation
Definition: pstypes.h:553
#define JOB_OBJECT_LIMIT_WORKINGSET
Definition: pstypes.h:208
enum _PSW32JOBCALLOUTTYPE PSW32JOBCALLOUTTYPE
#define PROCESS_PRIORITY_CLASS_ABOVE_NORMAL
Definition: pstypes.h:108
enum _JOBOBJECTINFOCLASS JOBOBJECTINFOCLASS
#define JOB_OBJECT_LIMIT_PROCESS_MEMORY
Definition: pstypes.h:216
struct _JOBOBJECT_BASIC_LIMIT_INFORMATION * PJOBOBJECT_BASIC_LIMIT_INFORMATION
#define JOB_OBJECT_LIMIT_SCHEDULING_CLASS
Definition: pstypes.h:215
#define JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
Definition: pstypes.h:221
struct _EJOB * PEJOB
struct _JOBOBJECT_SECURITY_LIMIT_INFORMATION JOBOBJECT_SECURITY_LIMIT_INFORMATION
#define JOB_OBJECT_LIMIT_PRIORITY_CLASS
Definition: pstypes.h:213
#define JOB_OBJECT_TERMINATE
Definition: pstypes.h:199
#define JOB_OBJECT_LIMIT_JOB_TIME
Definition: pstypes.h:210
@ JobObjectAssociateCompletionPortInformation
Definition: pstypes.h:498
@ JobObjectBasicLimitInformation
Definition: pstypes.h:493
@ JobObjectBasicAndIoAccountingInformation
Definition: pstypes.h:499
@ JobObjectBasicAccountingInformation
Definition: pstypes.h:492
@ JobObjectSecurityLimitInformation
Definition: pstypes.h:496
@ JobObjectExtendedLimitInformation
Definition: pstypes.h:500
@ JobObjectEndOfJobTimeInformation
Definition: pstypes.h:497
@ JobObjectBasicUIRestrictions
Definition: pstypes.h:495
@ JobObjectBasicProcessIdList
Definition: pstypes.h:494
@ MaxJobObjectInfoClass
Definition: pstypes.h:502
@ JobObjectJobSetInformation
Definition: pstypes.h:501
struct _JOBOBJECT_EXTENDED_LIMIT_INFORMATION JOBOBJECT_EXTENDED_LIMIT_INFORMATION
struct _JOBOBJECT_BASIC_ACCOUNTING_INFORMATION JOBOBJECT_BASIC_ACCOUNTING_INFORMATION
#define JOB_OBJECT_LIMIT_ACTIVE_PROCESS
Definition: pstypes.h:211
#define JOB_OBJECT_ASSIGN_PROCESS
Definition: pstypes.h:196
struct _JOBOBJECT_EXTENDED_LIMIT_INFORMATION * PJOBOBJECT_EXTENDED_LIMIT_INFORMATION
#define JOB_OBJECT_LIMIT_PROCESS_TIME
Definition: pstypes.h:209
#define JOB_OBJECT_SET_ATTRIBUTES
Definition: pstypes.h:197
#define JOB_OBJECT_QUERY
Definition: pstypes.h:198
#define JOB_OBJECT_MSG_NEW_PROCESS
Definition: pstypes.h:253
#define JOB_OBJECT_LIMIT_AFFINITY
Definition: pstypes.h:212
struct _JOBOBJECT_BASIC_UI_RESTRICTIONS * PJOBOBJECT_BASIC_UI_RESTRICTIONS
#define PROCESS_SET_QUOTA
Definition: pstypes.h:160
struct _JOBOBJECT_ASSOCIATE_COMPLETION_PORT JOBOBJECT_ASSOCIATE_COMPLETION_PORT
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
#define InterlockedOr
Definition: interlocked.h:239
#define InterlockedCompareExchangePointer
Definition: interlocked.h:144
#define InterlockedAnd
Definition: interlocked.h:77
#define KeEnterGuardedRegionThread(_Thread)
Definition: ke_x.h:27
#define KeLeaveGuardedRegionThread(_Thread)
Definition: ke_x.h:48
if(dx< 0)
Definition: linetemp.h:194
#define ASSERT(a)
Definition: mode.c:44
#define KernelMode
Definition: asm.h:38
#define IO_COMPLETION_MODIFY_STATE
Definition: iotypes.h:37
_In_ HANDLE ProcessHandle
Definition: mmfuncs.h:407
_In_ NTSTATUS ExitStatus
Definition: psfuncs.h:890
#define _In_reads_bytes_(s)
Definition: no_sal2.h:170
#define _Out_opt_
Definition: no_sal2.h:214
#define _Inout_
Definition: no_sal2.h:162
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
#define _Out_writes_bytes_(s)
Definition: no_sal2.h:178
#define THREAD_ALL_ACCESS
Definition: nt_native.h:1342
#define SYNCHRONIZE
Definition: nt_native.h:61
ULONG ACCESS_MASK
Definition: nt_native.h:40
#define NtCurrentProcess()
Definition: nt_native.h:1660
#define STANDARD_RIGHTS_READ
Definition: nt_native.h:65
struct _EPROCESS * PEPROCESS
Definition: nt_native.h:30
#define STANDARD_RIGHTS_ALL
Definition: nt_native.h:69
#define STANDARD_RIGHTS_WRITE
Definition: nt_native.h:66
#define STANDARD_RIGHTS_EXECUTE
Definition: nt_native.h:67
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
@ NotificationEvent
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1822
BOOLEAN NTAPI ExIsResourceAcquiredExclusiveLite(IN PERESOURCE Resource)
Definition: resource.c:1624
ULONG NTAPI ExIsResourceAcquiredSharedLite(IN PERESOURCE Resource)
Definition: resource.c:1663
PVOID NTAPI ExEnterCriticalRegionAndAcquireResourceShared(IN PERESOURCE Resource)
Definition: resource.c:2223
PVOID NTAPI ExEnterCriticalRegionAndAcquireResourceExclusive(IN PERESOURCE Resource)
Definition: resource.c:2194
VOID FASTCALL ExReleaseResourceAndLeaveCriticalRegion(IN PERESOURCE Resource)
Definition: resource.c:2283
POBJECT_TYPE IoCompletionType
Definition: iocomp.c:16
NTSTATUS NTAPI IoSetIoCompletion(IN PVOID IoCompletion, IN PVOID KeyContext, IN PVOID ApcContext, IN NTSTATUS IoStatus, IN ULONG_PTR IoStatusInformation, IN BOOLEAN Quota)
Definition: iocomp.c:147
KAFFINITY KeActiveProcessors
Definition: processor.c:16
VOID NTAPI KeQueryValuesProcess(IN PKPROCESS Process, PPROCESS_VALUES Values)
Definition: procobj.c:525
BOOLEAN NTAPI SeCheckPrivilegedObject(_In_ LUID PrivilegeValue, _In_ HANDLE ObjectHandle, _In_ ACCESS_MASK DesiredAccess, _In_ KPROCESSOR_MODE PreviousMode)
Checks a privileged object if such object has the specific privilege submitted by the caller.
Definition: priv.c:803
const LUID SeIncreaseBasePriorityPrivilege
Definition: priv.c:33
BOOLEAN NTAPI KeAreAllApcsDisabled(VOID)
Definition: apc.c:985
static NTSTATUS NTAPI PspQueryJobProcessIdListCallback(_In_ PEPROCESS Process, _Inout_ PVOID Context)
Definition: job.c:1445
NTSTATUS NTAPI NtSetInformationJobObject(_In_ HANDLE JobHandle, _In_ JOBOBJECTINFOCLASS JobInformationClass, _In_reads_bytes_(JobInformationLength) PVOID JobInformation, _In_ ULONG JobInformationLength)
Definition: job.c:2406
NTSTATUS NTAPI NtTerminateJobObject(_In_ HANDLE JobHandle, _In_ NTSTATUS ExitStatus)
Definition: job.c:2118
static NTSTATUS PspAssociateCompletionPortWithJob(_In_ PEJOB Job, _In_ PJOBOBJECT_ASSOCIATE_COMPLETION_PORT AssociateCpInfo)
Definition: job.c:1223
static NTSTATUS PspSetJobLimitsBasicOrExtended(_In_ PEJOB Job, _In_ PJOBOBJECT_EXTENDED_LIMIT_INFORMATION ExtendedLimit, _In_ BOOLEAN IsExtendedLimit)
Definition: job.c:966
NTSTATUS NTAPI PspInvokeW32JobCallout(_In_ PEJOB Job, _In_ PSW32JOBCALLOUTTYPE CalloutType, _In_opt_ PVOID Data)
Definition: job.c:1637
NTSTATUS NTAPI NtQueryInformationJobObject(_In_opt_ HANDLE JobHandle, _In_ JOBOBJECTINFOCLASS JobInformationClass, _Out_writes_bytes_(JobInformationLength) PVOID JobInformation, _In_ ULONG JobInformationLength, _Out_opt_ PULONG ReturnLength)
Definition: job.c:2179
static NTSTATUS NTAPI PspAssociateCompletionPortCallback(_In_ PEPROCESS Process, _In_ PVOID Context)
Definition: job.c:1174
NTSTATUS NTAPI PspSendJobMessageLocked(_In_ PEJOB Job, _In_ ULONG Message, _In_opt_ PVOID CompletionValue, _In_ BOOLEAN Quota)
Definition: job.c:397
NTSTATUS NTAPI NtIsProcessInJob(_In_ HANDLE ProcessHandle, _In_opt_ HANDLE JobHandle)
Definition: job.c:2014
static PEPROCESS PspGetNextProcessInJobLocked(_In_ PEJOB Job, _In_opt_ PEPROCESS PreviousProcess)
Definition: job.c:158
ULONG NTAPI PsGetJobUIRestrictionsClass(PEJOB Job)
Definition: job.c:1593
static NTSTATUS PspQueryJobProcessIdList(_In_ PEJOB Job, _Out_writes_bytes_(JobInformationLength) PJOBOBJECT_BASIC_PROCESS_ID_LIST ProcIdList, _In_ ULONG JobInformationLength, _Out_ PULONG ReturnRequiredLength)
Definition: job.c:1510
static PEPROCESS PspGetNextProcessInJob(_In_ PEJOB Job, _In_opt_ PEPROCESS PreviousProcess)
Definition: job.c:227
NTSTATUS NTAPI PspAssignProcessToJob(_In_ PEPROCESS Process, _In_ PEJOB Job)
Definition: job.c:432
VOID NTAPI PspInitializeJobStructures(VOID)
Definition: job.c:128
ULONG PspJobInfoAlign[]
Definition: job.c:71
static NTSTATUS NTAPI PspTerminateProcessCallback(_In_ PEPROCESS Process, _In_ PVOID Context)
Definition: job.c:711
VOID NTAPI PspCloseJob(_In_ PEPROCESS Process, _In_ PVOID ObjectBody, _In_ ACCESS_MASK GrantedAccess, _In_ ULONG_PTR ProcessHandleCount, _In_ ULONG_PTR SystemHandleCount)
Definition: job.c:845
NTSTATUS NTAPI NtCreateJobObject(_Out_ PHANDLE JobHandle, _In_ ACCESS_MASK DesiredAccess, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes)
Definition: job.c:1728
static NTSTATUS PspQueryJobBasicAccountingInfo(_In_ PEJOB Job, _Out_ PJOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION BasicAndIo)
Definition: job.c:1297
struct PSP_TERMINATE_PROCESS_CONTEXT * PPSP_TERMINATE_PROCESS_CONTEXT
VOID NTAPI PspExitProcessFromJob(_In_ PEPROCESS Process)
Definition: job.c:659
PVOID NTAPI PsGetJobLock(PEJOB Job)
Definition: job.c:1571
struct PSP_QUERY_JOB_PROCESS_ID_CONTEXT * PPSP_QUERY_JOB_PROCESS_ID_CONTEXT
NTSTATUS NTAPI PspTerminateJobObject(_In_ PEJOB Job, _In_ NTSTATUS ExitStatus)
Definition: job.c:788
static NTSTATUS PspQueryJobLimitInformation(_In_ PEJOB Job, _In_ BOOLEAN Extended, _Out_ PJOBOBJECT_EXTENDED_LIMIT_INFORMATION ExtendedLimit)
Definition: job.c:1379
VOID NTAPI PspDeleteJob(_In_ PVOID ObjectBody)
Definition: job.c:909
BOOLEAN PspUseJobSchedulingClasses
Definition: job.c:28
ULONG NTAPI PsGetJobSessionId(PEJOB Job)
Definition: job.c:1582
static FAST_MUTEX PsJobListLock
Definition: job.c:26
static NTSTATUS PspEnumerateProcessesInJobLocked(_In_ PEJOB Job, _In_ PJOB_ENUMERATOR_CALLBACK Callback, _In_opt_ PVOID Context)
Definition: job.c:347
static BOOLEAN PspDeactivateProcessFromJobLocked(_In_ PEJOB Job, _In_ PEPROCESS Process)
Definition: job.c:574
CHAR PspJobSchedulingClasses[PSP_JOB_SCHEDULING_CLASSES]
Definition: job.c:30
NTSTATUS NTAPI NtOpenJobObject(_Out_ PHANDLE JobHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes)
Definition: job.c:1862
VOID NTAPI PspRemoveProcessFromJob(_In_ PEPROCESS Process)
Definition: job.c:609
NTSTATUS NTAPI NtAssignProcessToJobObject(_In_ HANDLE JobHandle, _In_ HANDLE ProcessHandle)
Definition: job.c:1928
static NTSTATUS PspSetJobUIRestrictions(_In_ PEJOB Job, _In_ ULONG UIRestrictionsClass)
Definition: job.c:1678
LIST_ENTRY PsJobListHead
Definition: job.c:25
GENERIC_MAPPING PspJobMapping
Definition: job.c:44
NTSTATUS NTAPI NtCreateJobSet(IN ULONG NumJob, IN PJOB_SET_ARRAY UserJobSet, IN ULONG Flags)
Definition: job.c:1834
VOID NTAPI PsSetJobUIRestrictionsClass(PEJOB Job, ULONG UIRestrictionsClass)
Definition: job.c:1604
ULONG PspJobInfoLengths[]
Definition: job.c:56
POBJECT_TYPE PsJobType
Definition: job.c:23
NTSTATUS NTAPI PspEnumerateProcessesInJob(_In_ PEJOB Job, _In_ PJOB_ENUMERATOR_CALLBACK Callback, _In_opt_ PVOID Context)
Definition: job.c:290
POBJECT_TYPE PsProcessType
Definition: process.c:20
ULONG NTAPI PsGetProcessSessionId(IN PEPROCESS Process)
Definition: process.c:1193
_Out_ EXECUTION_STATE * PreviousFlags
Definition: ntpoapi.h:288
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define STATUS_PROCESS_IN_JOB
Definition: ntstatus.h:161
#define STATUS_QUOTA_EXCEEDED
Definition: ntstatus.h:398
#define STATUS_PROCESS_NOT_IN_JOB
Definition: ntstatus.h:160
#define STATUS_PROCESS_IS_TERMINATING
Definition: ntstatus.h:596
#define STATUS_INVALID_INFO_CLASS
Definition: ntstatus.h:333
BOOLEAN FASTCALL ObReferenceObjectSafe(IN PVOID Object)
Definition: obref.c:22
NTSTATUS NTAPI ObInsertObject(IN PVOID Object, IN PACCESS_STATE AccessState OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG ObjectPointerBias, OUT PVOID *NewObject OPTIONAL, OUT PHANDLE Handle)
Definition: obhandle.c:2957
NTSTATUS NTAPI ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, IN PACCESS_STATE PassedAccessState, IN ACCESS_MASK DesiredAccess, IN OUT PVOID ParseContext, OUT PHANDLE Handle)
Definition: obhandle.c:2554
NTSTATUS NTAPI ObCreateObject(IN KPROCESSOR_MODE ProbeMode OPTIONAL, IN POBJECT_TYPE Type, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN KPROCESSOR_MODE AccessMode, IN OUT PVOID ParseContext OPTIONAL, IN ULONG ObjectSize, IN ULONG PagedPoolCharge OPTIONAL, IN ULONG NonPagedPoolCharge OPTIONAL, OUT PVOID *Object)
Definition: oblife.c:1040
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:493
long LONG
Definition: pedump.c:60
char CHAR
Definition: pedump.c:57
#define PSP_JOB_BASIC_LIMIT_VALID_FLAGS
Definition: ps.h:78
NTSTATUS NTAPI PsTerminateProcess(IN PEPROCESS Process, IN NTSTATUS ExitStatus)
Definition: kill.c:126
#define PSP_JOB_CLOSE_DONE
Definition: ps.h:120
NTSTATUS(NTAPI * PJOB_ENUMERATOR_CALLBACK)(_In_ PEPROCESS Process, _In_opt_ PVOID Context)
Definition: ps.h:419
#define PSP_JOB_SCHEDULING_CLASSES
Definition: ps.h:73
#define PSP_JOB_NOT_REALLY_ACTIVE
Definition: ps.h:111
#define PSP_JOB_SCHEDULING_CLASS_DEFAULT
Definition: ps.h:72
#define PSP_JOB_EXTENDED_LIMIT_VALID_FLAGS
Definition: ps.h:87
#define PSP_JOB_ACCOUNTING_FOLDED
Definition: ps.h:112
#define PSP_JOB_TERMINATING
Definition: ps.h:121
PKWIN32_JOB_CALLOUT PspW32JobCallout
Definition: win32.c:20
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:204
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:104
#define _SEH2_END
Definition: pseh2_64.h:194
#define _SEH2_TRY
Definition: pseh2_64.h:93
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:207
#define ProbeForWriteHandle(Ptr)
Definition: probe.h:43
#define ProbeForWriteUlong(Ptr)
Definition: probe.h:36
Entry
Definition: section.c:5216
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
static void Exit(void)
Definition: sock.c:1330
_In_ PVOID Context
Definition: storport.h:2269
PJOBOBJECT_BASIC_PROCESS_ID_LIST ProcessIdList
Definition: job.c:118
ULONG LimitFlags
Definition: pstypes.h:1633
LIST_ENTRY ProcessListHead
Definition: pstypes.h:1621
ULONG UIRestrictionsClass
Definition: pstypes.h:1639
PVOID CompletionPort
Definition: pstypes.h:1644
KEVENT Event
Definition: pstypes.h:1619
ULONG SchedulingClass
Definition: pstypes.h:1647
PVOID CompletionKey
Definition: pstypes.h:1645
LIST_ENTRY JobLinks
Definition: pstypes.h:1620
ULONG JobFlags
Definition: pstypes.h:1669
EX_PUSH_LOCK MemoryLimitsLock
Definition: pstypes.h:1665
ERESOURCE JobLock
Definition: pstypes.h:1622
LIST_ENTRY JobSetLinks
Definition: pstypes.h:1667
ULONG SessionId
Definition: pstypes.h:1646
struct _EJOB * Job
Definition: pstypes.h:1440
ULONGLONG ReadOperationCount
Definition: pstypes.h:83
ULONGLONG WriteTransferCount
Definition: pstypes.h:87
ULONGLONG WriteOperationCount
Definition: pstypes.h:84
ULONGLONG ReadTransferCount
Definition: pstypes.h:86
ULONGLONG OtherOperationCount
Definition: pstypes.h:85
ULONGLONG OtherTransferCount
Definition: pstypes.h:88
JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation
Definition: pstypes.h:1741
KAPC_STATE ApcState
Definition: ketypes.h:1925
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
LARGE_INTEGER TotalUserTime
Definition: ke.h:47
IO_COUNTERS IoInfo
Definition: ke.h:48
LARGE_INTEGER TotalKernelTime
Definition: ke.h:46
uint32_t * PULONG_PTR
Definition: typedefs.h:65
uint32_t * PULONG
Definition: typedefs.h:59
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define NTAPI
Definition: typedefs.h:36
PVOID HANDLE
Definition: typedefs.h:73
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
int32_t * PLONG
Definition: typedefs.h:58
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
LONGLONG QuadPart
Definition: typedefs.h:114
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2664
@ ProcessHandleCount
Definition: winternl.h:1902
_In_ ULONG _Out_opt_ PULONG RequiredLength
Definition: wmifuncs.h:30
#define ExDeleteResource
Definition: exfuncs.h:345
#define ExInitializeResource
Definition: exfuncs.h:346
FORCEINLINE VOID ExInitializeFastMutex(_Out_ PFAST_MUTEX FastMutex)
Definition: exfuncs.h:274
FAST_MUTEX
Definition: extypes.h:17
#define IO_NO_INCREMENT
Definition: iotypes.h:598
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
#define ObDereferenceObject
Definition: obfuncs.h:203
#define ObReferenceObject
Definition: obfuncs.h:204
#define PsGetCurrentProcess
Definition: psfuncs.h:17
_In_ PSECURITY_SUBJECT_CONTEXT _In_ BOOLEAN _In_ ACCESS_MASK _In_ ACCESS_MASK _Outptr_opt_ PPRIVILEGE_SET _In_ PGENERIC_MAPPING _In_ KPROCESSOR_MODE _Out_ PACCESS_MASK GrantedAccess
Definition: sefuncs.h:20