ReactOS 0.4.17-dev-769-g1500a35
job.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Win32k Subsystem
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: Job object UI restrictions
5 * COPYRIGHT: Copyright 2026 Justin Miller <justin.miller@reactos.org>
6 */
7
8/*
9 * The kernel keeps the JOB_OBJECT_UILIMIT_* mask of a job, but it is win32k
10 * that enforces it, so every restricted job is handed to us through a callout
11 * (see PspInvokeW32JobCallout). We keep a JOBINFO per such job.
12 *
13 * Locking: the kernel takes the job lock before calling out, and the callout
14 * then takes the USER lock. To keep that the only order the two are held in,
15 * win32k never takes the job lock itself; gJobInfoList and everything on it
16 * is protected by the USER lock alone.
17 */
18
19#include <win32k.h>
20
22
23#define JOB_PROCESS_GROWTH 8
24#define JOB_HANDLE_GROWTH 16
25
26/* GLOBALS ********************************************************************/
27
29
30/* PRIVATE FUNCTIONS **********************************************************/
31
33static
35IntFindJobInfo(_In_ PEJOB pEJob)
36{
37 PJOBINFO pJobInfo;
38
40
41 for (pJobInfo = gJobInfoList; pJobInfo != NULL; pJobInfo = pJobInfo->Next)
42 {
43 if (pJobInfo->pEJob == pEJob)
44 return pJobInfo;
45 }
46
47 return NULL;
48}
49
51static
53IntCreateJobInfo(_In_ PEJOB pEJob)
54{
55 PJOBINFO pJobInfo;
57
59
61 if (pJobInfo == NULL)
62 {
63 ERR("Failed to allocate a JOBINFO for job %p\n", pEJob);
64 return NULL;
65 }
66
67 Status = RtlCreateAtomTable(37, &pJobInfo->pAtomTable);
68 if (!NT_SUCCESS(Status))
69 {
70 ERR("Failed to create the atom table of job %p: 0x%lx\n", pEJob, Status);
72 return NULL;
73 }
74
75 pJobInfo->pEJob = pEJob;
76
77 pJobInfo->Next = gJobInfoList;
78 gJobInfoList = pJobInfo;
79
80 TRACE("Created JOBINFO %p for job %p\n", pJobInfo, pEJob);
81 return pJobInfo;
82}
83
84/*
85 * Marks a process and its threads as belonging to a restricted job, so that
86 * enforcement is a flag test rather than a walk back to the job. user32 sees
87 * the thread flag through the CLIENTINFO.
88 */
90static
91VOID
92IntSetProcessRestricted(
94 _In_ BOOL bRestricted)
95{
96 PTHREADINFO pti;
98 BOOL bAttached = FALSE;
99
101
102 if (bRestricted)
103 ppi->W32PF_flags |= W32PF_JOBRESTRICTED;
104 else
105 ppi->W32PF_flags &= ~W32PF_JOBRESTRICTED;
106
107 /* The threads and the address space are going away anyway */
108 if (ppi->W32PF_flags & W32PF_TERMINATED)
109 return;
110
111 /* The CLIENTINFO of a thread lives in its own process */
112 if (ppi->peProcess != NULL && ppi != PsGetCurrentProcessWin32Process())
113 {
114 KeStackAttachProcess(&ppi->peProcess->Pcb, &ApcState);
115 bAttached = TRUE;
116 }
117
118 for (pti = ppi->ptiList; pti != NULL; pti = pti->ptiSibling)
119 {
120 if (bRestricted)
122 else
123 pti->TIF_flags &= ~TIF_JOBRESTRICTED;
124
126 {
127 if (pti->pClientInfo != NULL)
128 pti->pClientInfo->dwTIFlags = pti->TIF_flags;
129 }
131 {
132 /* Do nothing, the kernel side copy still stands */
133 NOTHING;
134 }
135 _SEH2_END;
136 }
137
138 if (bAttached)
140}
141
143static
144VOID
145IntDestroyJobInfo(_In_ PJOBINFO pJobInfo)
146{
147 PJOBINFO *ppJobInfo;
148 ULONG i;
149
151
152 /* Unlink it first, so nothing can find it */
153 for (ppJobInfo = &gJobInfoList; *ppJobInfo != NULL; ppJobInfo = &(*ppJobInfo)->Next)
154 {
155 if (*ppJobInfo == pJobInfo)
156 {
157 *ppJobInfo = pJobInfo->Next;
158 break;
159 }
160 }
161
162 for (i = 0; i < pJobInfo->ProcessCount; i++)
163 {
164 if (pJobInfo->pProcesses[i] != NULL)
165 {
166 IntSetProcessRestricted(pJobInfo->pProcesses[i], FALSE);
167 pJobInfo->pProcesses[i]->pW32Job = NULL;
168 }
169 }
170
171 if (pJobInfo->pProcesses != NULL)
172 ExFreePoolWithTag(pJobInfo->pProcesses, USERTAG_W32JOBEXTRA);
173
174 if (pJobInfo->pGrantedHandles != NULL)
175 ExFreePoolWithTag(pJobInfo->pGrantedHandles, USERTAG_W32JOBEXTRA);
176
177 if (pJobInfo->pAtomTable != NULL)
178 RtlDestroyAtomTable(pJobInfo->pAtomTable);
179
180 TRACE("Destroyed JOBINFO %p\n", pJobInfo);
182}
183
184/*
185 * Grows one of the arrays of a job by a fixed step. These lists are short and
186 * rarely added to, so doubling would waste far more than the copying saves.
187 * Returns the new array, or NULL when out of memory (the old one is kept).
188 */
190static
191PVOID
192IntGrowJobArray(
193 _In_opt_ PVOID pOldArray,
194 _In_ ULONG Used,
198{
199 PVOID pNewArray;
200 ULONG NewMax;
201
203
204 NewMax = *Max + Increment;
205
207 if (pNewArray == NULL)
208 return NULL;
209
210 if (pOldArray != NULL)
211 {
212 RtlCopyMemory(pNewArray, pOldArray, Used * EntrySize);
214 }
215
216 *Max = NewMax;
217 return pNewArray;
218}
219
221static
223IntAddProcessToJobInfo(
224 _In_ PJOBINFO pJobInfo,
225 _In_ PPROCESSINFO ppi)
226{
227 ULONG i;
228
230
231 /* Already a member? */
232 for (i = 0; i < pJobInfo->ProcessCount; i++)
233 {
234 if (pJobInfo->pProcesses[i] == ppi)
235 return STATUS_SUCCESS;
236 }
237
238 if (pJobInfo->ProcessCount >= pJobInfo->ProcessCountMax)
239 {
240 PPROCESSINFO *pProcesses;
241
242 pProcesses = IntGrowJobArray(pJobInfo->pProcesses,
243 pJobInfo->ProcessCount,
244 &pJobInfo->ProcessCountMax,
246 sizeof(PPROCESSINFO));
247 if (pProcesses == NULL)
248 return STATUS_NO_MEMORY;
249
250 pJobInfo->pProcesses = pProcesses;
251 }
252
253 pJobInfo->pProcesses[pJobInfo->ProcessCount++] = ppi;
254 ppi->pW32Job = pJobInfo;
255 IntSetProcessRestricted(ppi, TRUE);
256
257 TRACE("Process %p joined JOBINFO %p (restrictions 0x%lx)\n",
258 ppi, pJobInfo, pJobInfo->UIRestrictions);
259
260 return STATUS_SUCCESS;
261}
262
263/* Handles PsW32JobCalloutSetInformation */
264static
267 _In_ PEJOB pEJob,
268 _In_ ULONG UIRestrictions)
269{
271 PJOBINFO pJobInfo;
272 BOOL Created = FALSE;
273
275
276 pJobInfo = IntFindJobInfo(pEJob);
277
278 /* No restrictions left, so no state to keep */
279 if (UIRestrictions == 0)
280 {
281 if (pJobInfo != NULL)
282 IntDestroyJobInfo(pJobInfo);
283
284 goto Quit;
285 }
286
287 if (pJobInfo == NULL)
288 {
289 PPROCESSINFO ppi;
290
291 pJobInfo = IntCreateJobInfo(pEJob);
292 if (pJobInfo == NULL)
293 {
295 goto Quit;
296 }
297
298 Created = TRUE;
299
300 /* The job may already hold processes that connected to USER before
301 the restrictions were applied */
302 for (ppi = gppiList; ppi != NULL; ppi = ppi->ppiNext)
303 {
304 if (ppi->peProcess != NULL &&
305 PsGetProcessJob(ppi->peProcess) == pEJob)
306 {
307 Status = IntAddProcessToJobInfo(pJobInfo, ppi);
308 if (!NT_SUCCESS(Status))
309 goto Quit;
310 }
311 }
312 }
313
314 pJobInfo->UIRestrictions = UIRestrictions;
315
316Quit:
317 /* Undo a job we did not manage to finish building */
318 if (!NT_SUCCESS(Status) && Created)
319 IntDestroyJobInfo(pJobInfo);
320
321 UserLeave();
322 return Status;
323}
324
325/* Handles PsW32JobCalloutAddProcess */
326static
329 _In_ PEJOB pEJob,
330 _In_ PPROCESSINFO ppi)
331{
333 PJOBINFO pJobInfo;
334
336
337 pJobInfo = IntFindJobInfo(pEJob);
338 if (pJobInfo == NULL)
339 {
340 /* The kernel only calls us for jobs that have restrictions,
341 so we should have been told about this job already */
342 ERR("No JOBINFO for job %p\n", pEJob);
344 }
345 else
346 {
347 Status = IntAddProcessToJobInfo(pJobInfo, ppi);
348 }
349
350 UserLeave();
351 return Status;
352}
353
354/* Handles PsW32JobCalloutTerminate */
355static
358{
359 PJOBINFO pJobInfo;
360
362
363 pJobInfo = IntFindJobInfo(pEJob);
364 if (pJobInfo != NULL)
365 IntDestroyJobInfo(pJobInfo);
366
367 UserLeave();
368 return STATUS_SUCCESS;
369}
370
371/* Returns whether the handle was on the list */
373static
374BOOL
375IntRemoveGrantedHandle(
376 _In_ PJOBINFO pJobInfo,
377 _In_ HANDLE hUserHandle)
378{
379 ULONG i;
380
382
383 for (i = 0; i < pJobInfo->GrantedHandleCount; i++)
384 {
385 if (pJobInfo->pGrantedHandles[i] == hUserHandle)
386 {
387 /* Keep the array dense */
388 pJobInfo->pGrantedHandles[i] =
389 pJobInfo->pGrantedHandles[pJobInfo->GrantedHandleCount - 1];
390 pJobInfo->pGrantedHandles[pJobInfo->GrantedHandleCount - 1] = NULL;
391 pJobInfo->GrantedHandleCount--;
392 return TRUE;
393 }
394 }
395
396 return FALSE;
397}
398
400static
401BOOL
402IntIsHandleGrantedToJob(
403 _In_ PJOBINFO pJobInfo,
404 _In_ HANDLE hUserHandle)
405{
406 ULONG i;
407
409
410 for (i = 0; i < pJobInfo->GrantedHandleCount; i++)
411 {
412 if (pJobInfo->pGrantedHandles[i] == hUserHandle)
413 return TRUE;
414 }
415
416 return FALSE;
417}
418
420static
421BOOL
422IntGrantHandleToJob(
423 _In_ PJOBINFO pJobInfo,
424 _In_ HANDLE hUserHandle,
425 _In_ BOOL bGrant)
426{
428
429 /* Both granting and revoking need a handle that exists. Nothing is lost
430 by that: a handle that is destroyed while granted comes off the list
431 from IntCleanupGrantedHandle, not by the caller revoking it. */
432 if (!UserMarkHandleGranted(hUserHandle))
433 {
435 return FALSE;
436 }
437
438 if (!bGrant)
439 {
440 if (!IntRemoveGrantedHandle(pJobInfo, hUserHandle))
442
443 return TRUE;
444 }
445
446 if (IntIsHandleGrantedToJob(pJobInfo, hUserHandle))
447 return TRUE;
448
449 if (pJobInfo->GrantedHandleCount >= pJobInfo->GrantedHandleCountMax)
450 {
451 HANDLE *pGrantedHandles;
452
453 pGrantedHandles = IntGrowJobArray(pJobInfo->pGrantedHandles,
454 pJobInfo->GrantedHandleCount,
455 &pJobInfo->GrantedHandleCountMax,
457 sizeof(HANDLE));
458 if (pGrantedHandles == NULL)
459 {
461 return FALSE;
462 }
463
464 pJobInfo->pGrantedHandles = pGrantedHandles;
465 }
466
467 pJobInfo->pGrantedHandles[pJobInfo->GrantedHandleCount++] = hUserHandle;
468 return TRUE;
469}
470
471/* PUBLIC FUNCTIONS ***********************************************************/
472
473/* Called with the job lock held and without the USER lock */
475NTAPI
477{
478 switch (Parameters->CalloutType)
479 {
482 PtrToUlong(Parameters->Data));
483
485 return IntJobAddProcess((PEJOB)Parameters->Job,
486 (PPROCESSINFO)Parameters->Data);
487
489 return IntJobTerminate((PEJOB)Parameters->Job);
490
491 default:
492 ERR("Unknown job callout %d\n", Parameters->CalloutType);
494 }
495}
496
497/*
498 * Called when a process connects to USER. A process is normally assigned to
499 * its job while still suspended, so this is where restricted processes join.
500 *
501 * The job lock is deliberately not taken, as that would invert the order the
502 * callout path establishes; ppi is already on gppiList, so a concurrent
503 * restriction picks it up in IntJobSetRestrictions.
504 */
508IntJobConnectProcess(_In_ PPROCESSINFO ppi)
509{
510 PJOBINFO pJobInfo;
511 PEJOB pEJob;
512
514
515 pEJob = PsGetProcessJob(ppi->peProcess);
516 if (pEJob == NULL)
517 return STATUS_SUCCESS;
518
519 /* Unrestricted jobs have no state in win32k */
520 if (PsGetJobUIRestrictionsClass(pEJob) == 0)
521 return STATUS_SUCCESS;
522
523 pJobInfo = IntFindJobInfo(pEJob);
524 if (pJobInfo == NULL)
525 {
526 /* The restrictions have not reached us yet, or are being torn down */
527 return STATUS_SUCCESS;
528 }
529
530 return IntAddProcessToJobInfo(pJobInfo, ppi);
531}
532
533/* Called when a process disconnects from USER */
535VOID
537IntJobDisconnectProcess(_In_ PPROCESSINFO ppi)
538{
539 PJOBINFO pJobInfo;
540 ULONG i;
541
543
544 pJobInfo = ppi->pW32Job;
545 if (pJobInfo == NULL)
546 return;
547
548 for (i = 0; i < pJobInfo->ProcessCount; i++)
549 {
550 if (pJobInfo->pProcesses[i] == ppi)
551 {
552 /* Keep the array dense */
553 pJobInfo->pProcesses[i] = pJobInfo->pProcesses[pJobInfo->ProcessCount - 1];
554 pJobInfo->pProcesses[pJobInfo->ProcessCount - 1] = NULL;
555 pJobInfo->ProcessCount--;
556 break;
557 }
558 }
559
560 IntSetProcessRestricted(ppi, FALSE);
561 ppi->pW32Job = NULL;
562}
563
564/*
565 * Withdraws a freed USER handle from every job it was granted to. Handle
566 * values are reused, so a grant left on a dead handle would be inherited
567 * by whatever object is given the slot next.
568 */
570VOID
572IntCleanupGrantedHandle(_In_ HANDLE hUserHandle)
573{
574 PJOBINFO pJobInfo;
575
577
578 for (pJobInfo = gJobInfoList; pJobInfo != NULL; pJobInfo = pJobInfo->Next)
579 {
580 if (IntRemoveGrantedHandle(pJobInfo, hUserHandle))
581 TRACE("Withdrew handle %p from JOBINFO %p\n", hUserHandle, pJobInfo);
582 }
583}
584
585BOOL
588 _In_ HANDLE hUserHandle,
589 _In_ HANDLE hJob,
590 _In_ BOOL bGrant)
591{
592 PEJOB pEJob;
593 PJOBINFO pJobInfo;
595 BOOL Ret = FALSE;
596
597 if (hUserHandle == NULL)
598 {
600 return FALSE;
601 }
602
605 PsJobType,
606 UserMode,
607 (PVOID*)&pEJob,
608 NULL);
609 if (!NT_SUCCESS(Status))
610 {
612 return FALSE;
613 }
614
616
617 pJobInfo = IntFindJobInfo(pEJob);
618 if (pJobInfo == NULL)
619 {
620 /* A job with no UI restrictions at all keeps no granted list */
622 }
623 else
624 {
625 Ret = IntGrantHandleToJob(pJobInfo, hUserHandle, bGrant);
626 }
627
628 UserLeave();
629
630 ObDereferenceObject(pEJob);
631 return Ret;
632}
633
634/* EOF */
LONG NTSTATUS
Definition: precomp.h:26
#define ERR(fmt,...)
Definition: precomp.h:57
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:106
#define Max(a, b)
Definition: cdprocs.h:78
#define _Requires_lock_held_(lock)
#define _Requires_exclusive_lock_held_(lock)
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
_In_ HANDLE _In_ CONST PDXGKMDT_OPM_GET_INFO_PARAMETERS Parameters
Definition: dispmprt.h:321
#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
#define APIENTRY
Definition: api.h:79
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define ERROR_INVALID_HANDLE
Definition: compat.h:98
#define PtrToUlong(u)
Definition: config.h:107
#define PagedPool
Definition: env_spec_w32.h:308
IN OUT PLONG IN OUT PLONG Addend IN OUT PLONG IN LONG Increment
Definition: CrNtStubs.h:46
unsigned int BOOL
Definition: ntddk_ex.h:94
Status
Definition: gdiplustypes.h:24
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
@ PsW32JobCalloutTerminate
Definition: pstypes.h:555
@ PsW32JobCalloutAddProcess
Definition: pstypes.h:554
@ PsW32JobCalloutSetInformation
Definition: pstypes.h:553
#define JOB_OBJECT_SET_ATTRIBUTES
Definition: pstypes.h:197
#define TIF_JOBRESTRICTED
Definition: ntuser.h:295
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
#define NOTHING
Definition: input_list.c:10
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
static PVOID ExAllocatePoolZero(ULONG PoolType, SIZE_T NumberOfBytes, ULONG Tag)
Definition: precomp.h:45
#define UserMode
Definition: asm.h:39
NTSYSAPI NTSTATUS NTAPI RtlDestroyAtomTable(IN PRTL_ATOM_TABLE AtomTable)
Definition: atom.c:204
NTSYSAPI NTSTATUS NTAPI RtlCreateAtomTable(_In_ ULONG TableSize, _Inout_ PRTL_ATOM_TABLE *AtomTable)
#define _Inout_
Definition: no_sal2.h:162
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
#define FASTCALL
Definition: nt_native.h:50
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1769
ULONG NTAPI PsGetJobUIRestrictionsClass(PEJOB Job)
Definition: job.c:1593
POBJECT_TYPE PsJobType
Definition: job.c:23
PEJOB NTAPI PsGetProcessJob(PEPROCESS Process)
Definition: process.c:1123
PVOID NTAPI PsGetCurrentProcessWin32Process(VOID)
Definition: process.c:1213
BOOL FASTCALL UserIsEntered(VOID)
Definition: ntuser.c:225
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:255
ERESOURCE UserLock
Definition: ntuser.c:18
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:247
BOOL FASTCALL UserIsEnteredExclusive(VOID)
Definition: ntuser.c:231
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
VOID NTAPI KeStackAttachProcess(IN PKPROCESS Process, OUT PRKAPC_STATE ApcState)
Definition: procobj.c:704
VOID NTAPI KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
Definition: procobj.c:756
#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 STATUS_SUCCESS
Definition: shellext.h:65
#define TRACE(s)
Definition: solgame.cpp:4
Definition: job.h:12
PEJOB pEJob
Definition: job.h:14
PRTL_ATOM_TABLE pAtomTable
Definition: job.h:15
ULONG UIRestrictions
Definition: job.h:16
struct _JOBINFO * Next
Definition: job.h:13
ULONG ProcessCount
Definition: job.h:17
PPROCESSINFO * pProcesses
Definition: job.h:19
PPROCESSINFO ppiNext
Definition: win32.h:263
struct _JOBINFO * pW32Job
Definition: win32.h:277
PTHREADINFO ptiSibling
Definition: win32.h:117
struct _CLIENTINFO * pClientInfo
Definition: win32.h:95
FLONG TIF_flags
Definition: win32.h:96
uint32_t * PULONG
Definition: typedefs.h:59
#define NTAPI
Definition: typedefs.h:36
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define W32PF_TERMINATED
Definition: win32.h:16
#define W32PF_JOBRESTRICTED
Definition: win32.h:36
VOID FASTCALL SetLastNtError(_In_ NTSTATUS Status)
Definition: error.c:30
NTSTATUS NTAPI Win32kJobCallout(_In_ PWIN32_JOBCALLOUT_PARAMETERS Parameters)
Definition: job.c:476
BOOL APIENTRY NtUserUserHandleGrantAccess(_In_ HANDLE hUserHandle, _In_ HANDLE hJob, _In_ BOOL bGrant)
Definition: job.c:587
#define JOB_HANDLE_GROWTH
Definition: job.c:24
static NTSTATUS IntJobSetRestrictions(_In_ PEJOB pEJob, _In_ ULONG UIRestrictions)
Definition: job.c:266
static PJOBINFO gJobInfoList
Definition: job.c:28
static NTSTATUS IntJobTerminate(_In_ PEJOB pEJob)
Definition: job.c:357
static NTSTATUS IntJobAddProcess(_In_ PEJOB pEJob, _In_ PPROCESSINFO ppi)
Definition: job.c:328
#define JOB_PROCESS_GROWTH
Definition: job.c:23
PPROCESSINFO gppiList
Definition: main.c:31
BOOL FASTCALL UserMarkHandleGranted(HANDLE h)
Definition: object.c:726
#define USERTAG_W32JOBEXTRA
Definition: tags.h:242
#define USERTAG_W32JOB
Definition: tags.h:241
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:21
_In_ UCHAR EntrySize
Definition: iofuncs.h:642
KAPC_STATE
Definition: ketypes.h:1727
#define ObDereferenceObject
Definition: obfuncs.h:203