job.c
Upload User: caisha3
Upload Date: 2013-09-21
Package Size: 208739k
Code Size: 13k
Category:

Windows Develop

Development Platform:

Visual C++

  1. /****************************** Module Header ******************************
  2. * Module Name: job.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * This module contains the code to implement the job object in NTUSER.
  7. *
  8. * History:
  9. * 29-Jul-1997 CLupu   Created.
  10. ***************************************************************************/
  11. #include "precomp.h"
  12. PW32JOB CreateW32Job(PEJOB Job);
  13. VOID UpdateJob(PW32JOB pW32Job);
  14. void SetProcessFlags(PW32JOB pW32Job, PPROCESSINFO ppi);
  15. BOOL JobCalloutAddProcess(PW32JOB, PPROCESSINFO);
  16. BOOL JobCalloutTerminate(PW32JOB);
  17. /***************************************************************************
  18. * UserJobCallout
  19. *
  20. * History:
  21. * 29-Jul-1997 CLupu   Created.
  22. ***************************************************************************/
  23. NTSTATUS UserJobCallout(
  24.     PKWIN32_JOBCALLOUT_PARAMETERS Parm)
  25. {
  26.     NTSTATUS Status = STATUS_SUCCESS;
  27.     PW32JOB  pW32Job = NULL;
  28.     PEJOB    Job;
  29.     PSW32JOBCALLOUTTYPE CalloutType;
  30.     PVOID    Data;
  31.     Job = Parm->Job;
  32.     CalloutType = Parm->CalloutType;
  33.     Data = Parm->Data;
  34.     /*
  35.      * The EJOB lock must be acquired at this time.
  36.      */
  37.     UserAssert(ExIsResourceAcquiredExclusiveLite(&Job->JobLock));
  38.     UserAssert(gpresUser != NULL);
  39.     BEGIN_REENTERCRIT();
  40.     BEGINATOMICCHECK();
  41.     /*
  42.      * find the W32JOB in the global list (if any)
  43.      */
  44.     pW32Job = gpJobsList;
  45.     while (pW32Job) {
  46.         if (pW32Job->Job == Job) {
  47.             break;
  48.         }
  49.         pW32Job = pW32Job->pNext;
  50.     }
  51.     switch (CalloutType) {
  52.     case PsW32JobCalloutSetInformation:
  53.         if (pW32Job == NULL) {
  54.             /*
  55.              * The W32Job is not created yet. Assert that this is not
  56.              * a call to remove UI restrictions
  57.              */
  58.             UserAssert(Data != 0);
  59.             if ((pW32Job = CreateW32Job(Job)) == NULL) {
  60.                 Status = STATUS_UNSUCCESSFUL;
  61.                 break;
  62.             }
  63.         } else {
  64.             /*
  65.              * The W32Job structure is already created. Return if
  66.              * the restrictions are the same as before.
  67.              */
  68.             if (PtrToUlong(Data) == pW32Job->restrictions) {
  69.                 TAGMSG0(DBGTAG_Job, "UserJobCallout: SetInformation same as before");
  70.                 break;
  71.             }
  72.         }
  73.         /*
  74.          * Set the restrictions
  75.          */
  76.         pW32Job->restrictions = PtrToUlong(Data);
  77.         UpdateJob(pW32Job);
  78.         break;
  79.     case PsW32JobCalloutAddProcess:
  80.         /*
  81.          * 'Data' parameter is a pointer to W32PROCESS. So this callout
  82.          * happens only for GUI processes.
  83.          */
  84.         UserAssert(Job->UIRestrictionsClass != 0);
  85.         /*
  86.          * Assert that the W32JOB structure is already created.
  87.          */
  88.         UserAssert(pW32Job != NULL);
  89.         TAGMSG3(DBGTAG_Job, "UserJobCallout: AddProcess Job 0x%x W32Job 0x%x Process 0x%x",
  90.                 Job, pW32Job, (ULONG_PTR)Data);
  91.         /*
  92.          * this callout must be only for GUI processes
  93.          */
  94.         UserAssert(Data != NULL);
  95.         JobCalloutAddProcess(pW32Job, (PPROCESSINFO)Data);
  96.         break;
  97.     case PsW32JobCalloutTerminate:
  98.         TAGMSG2(DBGTAG_Job, "UserJobCallout: Terminate Job 0x%x W32Job 0x%x",
  99.                 Job, pW32Job);
  100.         if (pW32Job) {
  101.             JobCalloutTerminate(pW32Job);
  102.         }
  103.         break;
  104.     default:
  105.         TAGMSG2(DBGTAG_Job, "UserJobCallout: Invalid callout 0x%x Job 0x%x",
  106.                 CalloutType, Job);
  107.         Status = STATUS_NOT_IMPLEMENTED;
  108.         break;
  109.     }
  110.     ENDATOMICCHECK();
  111.     END_REENTERCRIT();
  112.     return Status;
  113. }
  114. /***************************************************************************
  115. * CreateW32Job
  116. *
  117. * Creates a W32Job
  118. *
  119. * History:
  120. * 18-Mar-1998 CLupu   Created.
  121. ***************************************************************************/
  122. PW32JOB CreateW32Job(
  123.     PEJOB Job)
  124. {
  125.     PW32JOB pW32Job;
  126.     TAGMSG1(DBGTAG_Job, "CreateW32Job: EJOB 0x%x", Job);
  127.     pW32Job = UserAllocPoolZInit(sizeof(W32JOB), TAG_W32JOB);
  128.     if (pW32Job == NULL) {
  129.         RIPMSG0(RIP_ERROR, "CreateW32Job: memory allocation error");
  130.         return NULL;
  131.     }
  132.     /*
  133.      * Create the global atom table for this job
  134.      */
  135.     CreateGlobalAtomTable(&pW32Job->pAtomTable);
  136.     if (pW32Job->pAtomTable == NULL) {
  137.         RIPMSG1(RIP_ERROR, "CreateW32Job: fail to create the atom table for job 0x%x",
  138.                 pW32Job);
  139.         UserFreePool(pW32Job);
  140.         return NULL;
  141.     }
  142.     /*
  143.      * Link it in the W32 job's list
  144.      */
  145.     pW32Job->pNext = gpJobsList;
  146.     gpJobsList = pW32Job;
  147.     pW32Job->Job = Job;
  148.     TAGMSG2(DBGTAG_Job, "CreateW32Job: pW32Job 0x%x created for EJOB 0x%x",
  149.             pW32Job, Job);
  150.     return pW32Job;
  151. }
  152. /***************************************************************************
  153. * UpdateJob
  154. *
  155. * Walks the processinfo list in userk to update all the processes assigned
  156. * to this job .
  157. *
  158. * History:
  159. * 20-Mar-1998 CLupu   Created.
  160. ***************************************************************************/
  161. VOID UpdateJob(
  162.     PW32JOB pW32Job)
  163. {
  164.     PPROCESSINFO ppi;
  165.     UserAssert(ExIsResourceAcquiredExclusiveLite(&pW32Job->Job->JobLock));
  166.     CheckCritIn();
  167.     TAGMSG1(DBGTAG_Job, "UpdateJob: pW32Job 0x%x", pW32Job);
  168.     /*
  169.      * walk the GUI processes list to see if any new process got
  170.      * assigned to the current job.
  171.      */
  172.     ppi = gppiList;
  173.     while (ppi) {
  174.         if (ppi->Process->Job == pW32Job->Job) {
  175.             /*
  176.              * the process is assigned to this job
  177.              */
  178.             if (ppi->pW32Job == NULL) {
  179.                 /*
  180.                  * add the process to the W32 job
  181.                  */
  182.                 JobCalloutAddProcess(pW32Job, ppi);
  183.             } else {
  184.                 /*
  185.                  * The process is already added to the job. Just
  186.                  * update the restrictions.
  187.                  */
  188.                 SetProcessFlags(pW32Job, ppi);
  189.             }
  190.         }
  191.         ppi = ppi->ppiNextRunning;
  192.     }
  193. }
  194. /***************************************************************************
  195. * RemoveProcessFromJob
  196. *
  197. * This is called during the delete process callout.
  198. *
  199. * History:
  200. * 30-Jul-1997 CLupu   Created.
  201. ***************************************************************************/
  202. BOOL RemoveProcessFromJob(
  203.     PPROCESSINFO ppi)
  204. {
  205.     PW32JOB pW32Job;
  206.     UINT    ip;
  207.     CheckCritIn();
  208.     pW32Job = ppi->pW32Job;
  209.     TAGMSG2(DBGTAG_Job, "RemoveProcessFromJob: ppi 0x%x pW32Job 0x%x",
  210.             ppi, pW32Job);
  211.     /*
  212.      * The job might not have UI restrictions
  213.      */
  214.     if (pW32Job == NULL) {
  215.         return FALSE;
  216.     }
  217.     /*
  218.      * remove the ppi from the job's ppi table
  219.      */
  220.     for (ip = 0; ip < pW32Job->uProcessCount; ip++) {
  221.         UserAssert(pW32Job->ppiTable[ip]->pW32Job == pW32Job);
  222.         if (ppi == pW32Job->ppiTable[ip]) {
  223.             ppi->pW32Job = NULL;
  224.             RtlMoveMemory(pW32Job->ppiTable + ip,
  225.                           pW32Job->ppiTable + ip + 1,
  226.                           (pW32Job->uProcessCount - ip - 1) * sizeof(PPROCESSINFO));
  227.             (pW32Job->uProcessCount)--;
  228.             /*
  229.              * free the process array if this is the last one.
  230.              */
  231.             if (pW32Job->uProcessCount == 0) {
  232.                 UserFreePool(pW32Job->ppiTable);
  233.                 pW32Job->ppiTable = NULL;
  234.                 pW32Job->uMaxProcesses = 0;
  235.             }
  236.             
  237.             TAGMSG2(DBGTAG_Job, "RemoveProcessFromJob: ppi 0x%x removed from pW32Job 0x%x",
  238.                     ppi, pW32Job);
  239.             return TRUE;
  240.         }
  241.     }
  242.     
  243.     TAGMSG2(DBGTAG_Job, "RemoveProcessFromJob: ppi 0x%x not found in pW32Job 0x%x",
  244.             ppi, pW32Job);
  245.     UserAssert(0);
  246.     return FALSE;
  247. }
  248. /***************************************************************************
  249. * SetProcessFlags
  250. *
  251. * History:
  252. * 29-Jul-1997 CLupu   Created.
  253. ***************************************************************************/
  254. void SetProcessFlags(
  255.     PW32JOB      pW32Job,
  256.     PPROCESSINFO ppi)
  257. {
  258.     PTHREADINFO pti;
  259.     CheckCritIn();
  260.     TAGMSG3(DBGTAG_Job, "SetProcessFlags: pW32Job 0x%x ppi 0x%x restrictions 0x%x",
  261.             pW32Job, ppi, pW32Job->restrictions);
  262.     UserAssert(ppi->pW32Job == pW32Job);
  263.     if (pW32Job->restrictions == 0) {
  264.         ((PW32PROCESS)ppi)->W32PF_Flags &= ~W32PF_RESTRICTED;
  265.     } else {
  266.         ((PW32PROCESS)ppi)->W32PF_Flags |= W32PF_RESTRICTED;
  267.     }
  268.     KeAttachProcess(&ppi->Process->Pcb);
  269.     /*
  270.      * walk the pti list and set the restricted flag as appropriate
  271.      */
  272.     pti = ppi->ptiList;
  273.     if (pW32Job->restrictions == 0) {
  274.         while (pti) {
  275.             pti->TIF_flags &= ~TIF_RESTRICTED;
  276.             pti->pClientInfo->dwTIFlags &= ~TIF_RESTRICTED;
  277.             pti = pti->ptiSibling;
  278.         }
  279.     } else {
  280.         while (pti) {
  281.             pti->TIF_flags |= TIF_RESTRICTED;
  282.             pti->pClientInfo->dwTIFlags |= TIF_RESTRICTED;
  283.             pti = pti->ptiSibling;
  284.         }
  285.     }
  286.     KeDetachProcess();
  287. }
  288. /***************************************************************************
  289. * JobCalloutAddProcess
  290. *
  291. * History:
  292. * 30-Jul-1997 CLupu   Created.
  293. ***************************************************************************/
  294. BOOL JobCalloutAddProcess(
  295.     PW32JOB      pW32Job,
  296.     PPROCESSINFO ppi)
  297. {
  298.     PPROCESSINFO* ppiTable;
  299.     CheckCritIn();
  300.     UserAssert(pW32Job != NULL);
  301.     /*
  302.      * This process is not yet initialized
  303.      */
  304.     if (ppi->Process == NULL) {
  305.         return FALSE;
  306.     }
  307.     if (!(ppi->W32PF_Flags & W32PF_PROCESSCONNECTED)) {
  308.         TAGMSG2(DBGTAG_Job, "JobCalloutAddProcess: pW32Job 0x%x ppi 0x%x not yet initialized",
  309.                 pW32Job, ppi);
  310.         return FALSE;
  311.     }
  312.     TAGMSG2(DBGTAG_Job, "JobCalloutAddProcess: pW32Job 0x%x ppi 0x%x",
  313.             pW32Job, ppi);
  314. #if DBG
  315.     /*
  316.      * Make sure the process is not already in the job's process list
  317.      */
  318.     {
  319.         UINT ip;
  320.         for (ip = 0; ip < pW32Job->uProcessCount; ip++) {
  321.             UserAssert(pW32Job->ppiTable[ip]->pW32Job == pW32Job);
  322.             UserAssert(ppi != pW32Job->ppiTable[ip]);
  323.         }
  324.     }
  325. #endif // DBG
  326.     /*
  327.      * save the pW32Job pointer in the process info
  328.      */
  329.     UserAssert(ppi->pW32Job == NULL);
  330.     ppi->pW32Job = pW32Job;
  331.     if (pW32Job->uProcessCount == pW32Job->uMaxProcesses) {
  332.         /*
  333.          * No more room. Allocate more space for the process table
  334.          */
  335.         if (pW32Job->uMaxProcesses == 0) {
  336.             UserAssert(pW32Job->ppiTable == NULL);
  337.             ppiTable = UserAllocPool(JP_DELTA * sizeof(PPROCESSINFO), TAG_W32JOBEXTRA);
  338.         } else {
  339.             UserAssert(pW32Job->ppiTable != NULL);
  340.             ppiTable = UserReAllocPool(pW32Job->ppiTable,
  341.                                        pW32Job->uMaxProcesses * sizeof(PPROCESSINFO),
  342.                                        (pW32Job->uMaxProcesses + JP_DELTA) * sizeof(PPROCESSINFO),
  343.                                        TAG_W32JOBEXTRA);
  344.         }
  345.         if (ppiTable == NULL) {
  346.             RIPMSG0(RIP_ERROR, "JobCalloutAddProcess: memory allocation errorn");
  347.             return FALSE;
  348.         }
  349.         pW32Job->ppiTable = ppiTable;
  350.         pW32Job->uMaxProcesses += JP_DELTA;
  351.     }
  352.     /*
  353.      * now add the process to the job
  354.      */
  355.     pW32Job->ppiTable[pW32Job->uProcessCount] = ppi;
  356.     (pW32Job->uProcessCount)++;
  357.     SetProcessFlags(pW32Job, ppi);
  358.     return TRUE;
  359. }
  360. /***************************************************************************
  361. * JobCalloutTerminate
  362. *
  363. * This is called during the job object delete routine.
  364. *
  365. * History:
  366. * 30-Jul-1997 CLupu   Created.
  367. ***************************************************************************/
  368. BOOL JobCalloutTerminate(
  369.     PW32JOB pW32Job)
  370. {
  371.     CheckCritIn();
  372.     UserAssert(pW32Job != NULL);
  373.     TAGMSG1(DBGTAG_Job, "JobCalloutTerminate: pW32Job 0x%x", pW32Job);
  374.     /*
  375.      * No processes should be attached to this job
  376.      */
  377.     UserAssert(pW32Job->ppiTable == NULL);
  378.     UserAssert(pW32Job->uProcessCount == 0);
  379.     UserAssert(pW32Job->uMaxProcesses == 0);
  380.     if (pW32Job->pgh) {
  381.         UserAssert(pW32Job->ughCrt > 0);
  382.         UserAssert(pW32Job->ughMax > 0);
  383.         UserFreePool(pW32Job->pgh);
  384.         pW32Job->pgh    = NULL;
  385.         pW32Job->ughCrt = 0;
  386.         pW32Job->ughMax = 0;
  387.     }
  388.     /*
  389.      * remove the W32 job from the job's list
  390.      */
  391.     REMOVE_FROM_LIST(W32JOB, gpJobsList, pW32Job, pNext);
  392.     RtlDestroyAtomTable(pW32Job->pAtomTable);
  393.     UserFreePool(pW32Job);
  394.     return TRUE;
  395. }