Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

510 lines
13 KiB

/****************************** Module Header ******************************\
* Module Name: job.c
*
* Copyright (c) 1985 - 1999, Microsoft Corporation
*
* This module contains the code to implement the job object in NTUSER.
*
* History:
* 29-Jul-1997 CLupu Created.
\***************************************************************************/
#include "precomp.h"
PW32JOB CreateW32Job(PEJOB Job);
VOID UpdateJob(PW32JOB pW32Job);
void SetProcessFlags(PW32JOB pW32Job, PPROCESSINFO ppi);
BOOL JobCalloutAddProcess(PW32JOB, PPROCESSINFO);
BOOL JobCalloutTerminate(PW32JOB);
/***************************************************************************\
* UserJobCallout
*
* History:
* 29-Jul-1997 CLupu Created.
\***************************************************************************/
NTSTATUS UserJobCallout(
PKWIN32_JOBCALLOUT_PARAMETERS Parm)
{
NTSTATUS Status = STATUS_SUCCESS;
PW32JOB pW32Job = NULL;
PEJOB Job;
PSW32JOBCALLOUTTYPE CalloutType;
PVOID Data;
Job = Parm->Job;
CalloutType = Parm->CalloutType;
Data = Parm->Data;
/*
* The EJOB lock must be acquired at this time.
*/
UserAssert(ExIsResourceAcquiredExclusiveLite(PsGetJobLock(Job)));
UserAssert(gpresUser != NULL);
BEGIN_REENTERCRIT();
BEGINATOMICCHECK();
/*
* find the W32JOB in the global list (if any)
*/
pW32Job = gpJobsList;
while (pW32Job) {
if (pW32Job->Job == Job) {
break;
}
pW32Job = pW32Job->pNext;
}
switch (CalloutType) {
case PsW32JobCalloutSetInformation:
if (pW32Job == NULL) {
/*
* The W32Job is not created yet. Assert that this is not
* a call to remove UI restrictions
*/
UserAssert(Data != 0);
if ((pW32Job = CreateW32Job(Job)) == NULL) {
Status = STATUS_UNSUCCESSFUL;
break;
}
} else {
/*
* The W32Job structure is already created. Return if
* the restrictions are the same as before.
*/
if (PtrToUlong(Data) == pW32Job->restrictions) {
TAGMSG0(DBGTAG_Job, "UserJobCallout: SetInformation same as before");
break;
}
}
/*
* Set the restrictions
*/
pW32Job->restrictions = PtrToUlong(Data);
UpdateJob(pW32Job);
break;
case PsW32JobCalloutAddProcess:
/*
* 'Data' parameter is a pointer to W32PROCESS. So this callout
* happens only for GUI processes.
*/
UserAssert(PsGetJobUIRestrictionsClass(Job) != 0);
/*
* Assert that the W32JOB structure is already created.
*/
UserAssert(pW32Job != NULL);
TAGMSG3(DBGTAG_Job, "UserJobCallout: AddProcess Job %#p W32Job %#p Process %#p",
Job, pW32Job, (ULONG_PTR)Data);
/*
* this callout must be only for GUI processes
*/
UserAssert(Data != NULL);
JobCalloutAddProcess(pW32Job, (PPROCESSINFO)Data);
break;
case PsW32JobCalloutTerminate:
TAGMSG2(DBGTAG_Job, "UserJobCallout: Terminate Job %#p W32Job %#p",
Job, pW32Job);
if (pW32Job) {
JobCalloutTerminate(pW32Job);
}
break;
default:
TAGMSG2(DBGTAG_Job, "UserJobCallout: Invalid callout 0x%x Job %#p",
CalloutType, Job);
Status = STATUS_NOT_IMPLEMENTED;
break;
}
ENDATOMICCHECK();
END_REENTERCRIT();
return Status;
}
/***************************************************************************\
* CreateW32Job
*
* Creates a W32Job
*
* History:
* 18-Mar-1998 CLupu Created.
\***************************************************************************/
PW32JOB CreateW32Job(
PEJOB Job)
{
PW32JOB pW32Job;
TAGMSG1(DBGTAG_Job, "CreateW32Job: EJOB %#p", Job);
pW32Job = UserAllocPoolZInit(sizeof(W32JOB), TAG_W32JOB);
if (pW32Job == NULL) {
RIPMSG0(RIP_ERROR, "CreateW32Job: memory allocation error");
return NULL;
}
/*
* Create the global atom table for this job
*/
CreateGlobalAtomTable(&pW32Job->pAtomTable);
if (pW32Job->pAtomTable == NULL) {
RIPMSG1(RIP_ERROR, "CreateW32Job: fail to create the atom table for job %#p",
pW32Job);
UserFreePool(pW32Job);
return NULL;
}
/*
* Link it in the W32 job's list
*/
pW32Job->pNext = gpJobsList;
gpJobsList = pW32Job;
pW32Job->Job = Job;
TAGMSG2(DBGTAG_Job, "CreateW32Job: pW32Job %#P created for EJOB %#p",
pW32Job, Job);
return pW32Job;
}
/***************************************************************************\
* UpdateJob
*
* Walks the processinfo list in userk to update all the processes assigned
* to this job .
*
* History:
* 20-Mar-1998 CLupu Created.
\***************************************************************************/
VOID UpdateJob(
PW32JOB pW32Job)
{
PPROCESSINFO ppi;
UserAssert(ExIsResourceAcquiredExclusiveLite(PsGetJobLock(pW32Job->Job)));
CheckCritIn();
TAGMSG1(DBGTAG_Job, "UpdateJob: pW32Job %#p", pW32Job);
/*
* walk the GUI processes list to see if any new process got
* assigned to the current job.
*/
ppi = gppiList;
while (ppi) {
if (PsGetProcessJob(ppi->Process) == pW32Job->Job) {
/*
* the process is assigned to this job
*/
if (ppi->pW32Job == NULL) {
/*
* add the process to the W32 job
*/
JobCalloutAddProcess(pW32Job, ppi);
} else {
/*
* The process is already added to the job. Just
* update the restrictions.
*/
SetProcessFlags(pW32Job, ppi);
}
}
ppi = ppi->ppiNextRunning;
}
}
/***************************************************************************\
* RemoveProcessFromJob
*
* This is called during the delete process callout.
*
* History:
* 30-Jul-1997 CLupu Created.
\***************************************************************************/
BOOL RemoveProcessFromJob(
PPROCESSINFO ppi)
{
PW32JOB pW32Job;
UINT ip;
CheckCritIn();
pW32Job = ppi->pW32Job;
TAGMSG2(DBGTAG_Job, "RemoveProcessFromJob: ppi %#p pW32Job %#p",
ppi, pW32Job);
/*
* The job might not have UI restrictions
*/
if (pW32Job == NULL) {
return FALSE;
}
/*
* remove the ppi from the job's ppi table
*/
for (ip = 0; ip < pW32Job->uProcessCount; ip++) {
UserAssert(pW32Job->ppiTable[ip]->pW32Job == pW32Job);
if (ppi == pW32Job->ppiTable[ip]) {
ppi->pW32Job = NULL;
RtlMoveMemory(pW32Job->ppiTable + ip,
pW32Job->ppiTable + ip + 1,
(pW32Job->uProcessCount - ip - 1) * sizeof(PPROCESSINFO));
(pW32Job->uProcessCount)--;
/*
* free the process array if this is the last one.
*/
if (pW32Job->uProcessCount == 0) {
UserFreePool(pW32Job->ppiTable);
pW32Job->ppiTable = NULL;
pW32Job->uMaxProcesses = 0;
}
TAGMSG2(DBGTAG_Job, "RemoveProcessFromJob: ppi %#p removed from pW32Job %#p",
ppi, pW32Job);
return TRUE;
}
}
TAGMSG2(DBGTAG_Job, "RemoveProcessFromJob: ppi %#p not found in pW32Job %#p",
ppi, pW32Job);
UserAssert(0);
return FALSE;
}
/***************************************************************************\
* SetProcessFlags
*
* History:
* 29-Jul-1997 CLupu Created.
\***************************************************************************/
void SetProcessFlags(
PW32JOB pW32Job,
PPROCESSINFO ppi)
{
PTHREADINFO pti;
CheckCritIn();
TAGMSG3(DBGTAG_Job, "SetProcessFlags: pW32Job %#p ppi %#p restrictions %#p",
pW32Job, ppi, pW32Job->restrictions);
UserAssert(ppi->pW32Job == pW32Job);
if (pW32Job->restrictions == 0) {
((PW32PROCESS)ppi)->W32PF_Flags &= ~W32PF_RESTRICTED;
} else {
((PW32PROCESS)ppi)->W32PF_Flags |= W32PF_RESTRICTED;
}
KeAttachProcess(PsGetProcessPcb(ppi->Process));
/*
* walk the pti list and set the restricted flag as appropriate
*/
pti = ppi->ptiList;
if (pW32Job->restrictions == 0) {
while (pti) {
try {
pti->pClientInfo->dwTIFlags &= ~TIF_RESTRICTED;
} except (W32ExceptionHandler(TRUE, RIP_WARNING)) {
continue;
}
pti->TIF_flags &= ~TIF_RESTRICTED;
pti = pti->ptiSibling;
}
} else {
while (pti) {
try {
pti->pClientInfo->dwTIFlags |= TIF_RESTRICTED;
} except (W32ExceptionHandler(TRUE, RIP_WARNING)) {
continue;
}
pti->TIF_flags |= TIF_RESTRICTED;
pti = pti->ptiSibling;
}
}
KeDetachProcess();
}
/***************************************************************************\
* JobCalloutAddProcess
*
* History:
* 30-Jul-1997 CLupu Created.
\***************************************************************************/
BOOL JobCalloutAddProcess(
PW32JOB pW32Job,
PPROCESSINFO ppi)
{
PPROCESSINFO* ppiTable;
CheckCritIn();
UserAssert(pW32Job != NULL);
/*
* This process is not yet initialized
*/
if (ppi->Process == NULL) {
return FALSE;
}
if (!(ppi->W32PF_Flags & W32PF_PROCESSCONNECTED)) {
TAGMSG2(DBGTAG_Job, "JobCalloutAddProcess: pW32Job %#p ppi %#p not yet initialized",
pW32Job, ppi);
return FALSE;
}
TAGMSG2(DBGTAG_Job, "JobCalloutAddProcess: pW32Job %#p ppi %#p",
pW32Job, ppi);
#if DBG
/*
* Make sure the process is not already in the job's process list
*/
{
UINT ip;
for (ip = 0; ip < pW32Job->uProcessCount; ip++) {
UserAssert(pW32Job->ppiTable[ip]->pW32Job == pW32Job);
UserAssert(ppi != pW32Job->ppiTable[ip]);
}
}
#endif // DBG
/*
* save the pW32Job pointer in the process info
*/
UserAssert(ppi->pW32Job == NULL);
ppi->pW32Job = pW32Job;
if (pW32Job->uProcessCount == pW32Job->uMaxProcesses) {
/*
* No more room. Allocate more space for the process table
*/
if (pW32Job->uMaxProcesses == 0) {
UserAssert(pW32Job->ppiTable == NULL);
ppiTable = UserAllocPool(JP_DELTA * sizeof(PPROCESSINFO), TAG_W32JOBEXTRA);
} else {
UserAssert(pW32Job->ppiTable != NULL);
ppiTable = UserReAllocPool(pW32Job->ppiTable,
pW32Job->uMaxProcesses * sizeof(PPROCESSINFO),
(pW32Job->uMaxProcesses + JP_DELTA) * sizeof(PPROCESSINFO),
TAG_W32JOBEXTRA);
}
if (ppiTable == NULL) {
RIPMSG0(RIP_ERROR, "JobCalloutAddProcess: memory allocation error\n");
return FALSE;
}
pW32Job->ppiTable = ppiTable;
pW32Job->uMaxProcesses += JP_DELTA;
}
/*
* now add the process to the job
*/
pW32Job->ppiTable[pW32Job->uProcessCount] = ppi;
(pW32Job->uProcessCount)++;
SetProcessFlags(pW32Job, ppi);
return TRUE;
}
/***************************************************************************\
* JobCalloutTerminate
*
* This is called during the job object delete routine.
*
* History:
* 30-Jul-1997 CLupu Created.
\***************************************************************************/
BOOL JobCalloutTerminate(
PW32JOB pW32Job)
{
CheckCritIn();
UserAssert(pW32Job != NULL);
TAGMSG1(DBGTAG_Job, "JobCalloutTerminate: pW32Job %#p", pW32Job);
/*
* No processes should be attached to this job
*/
UserAssert(pW32Job->ppiTable == NULL);
UserAssert(pW32Job->uProcessCount == 0);
UserAssert(pW32Job->uMaxProcesses == 0);
if (pW32Job->pgh) {
UserAssert(pW32Job->ughCrt > 0);
UserAssert(pW32Job->ughMax > 0);
UserFreePool(pW32Job->pgh);
pW32Job->pgh = NULL;
pW32Job->ughCrt = 0;
pW32Job->ughMax = 0;
}
/*
* remove the W32 job from the job's list
*/
REMOVE_FROM_LIST(W32JOB, gpJobsList, pW32Job, pNext);
RtlDestroyAtomTable(pW32Job->pAtomTable);
UserFreePool(pW32Job);
return TRUE;
}