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

  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(PsGetJobLock(Job)));
  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(PsGetJobUIRestrictionsClass(Job) != 0);
  85. /*
  86. * Assert that the W32JOB structure is already created.
  87. */
  88. UserAssert(pW32Job != NULL);
  89. TAGMSG3(DBGTAG_Job, "UserJobCallout: AddProcess Job %#p W32Job %#p Process %#p",
  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 %#p W32Job %#p",
  99. Job, pW32Job);
  100. if (pW32Job) {
  101. JobCalloutTerminate(pW32Job);
  102. }
  103. break;
  104. default:
  105. TAGMSG2(DBGTAG_Job, "UserJobCallout: Invalid callout 0x%x Job %#p",
  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 %#p", 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 %#p",
  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 %#P created for EJOB %#p",
  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(PsGetJobLock(pW32Job->Job)));
  166. CheckCritIn();
  167. TAGMSG1(DBGTAG_Job, "UpdateJob: pW32Job %#p", 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 (PsGetProcessJob(ppi->Process) == 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 %#p pW32Job %#p",
  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. TAGMSG2(DBGTAG_Job, "RemoveProcessFromJob: ppi %#p removed from pW32Job %#p",
  237. ppi, pW32Job);
  238. return TRUE;
  239. }
  240. }
  241. TAGMSG2(DBGTAG_Job, "RemoveProcessFromJob: ppi %#p not found in pW32Job %#p",
  242. ppi, pW32Job);
  243. UserAssert(0);
  244. return FALSE;
  245. }
  246. /***************************************************************************\
  247. * SetProcessFlags
  248. *
  249. * History:
  250. * 29-Jul-1997 CLupu Created.
  251. \***************************************************************************/
  252. void SetProcessFlags(
  253. PW32JOB pW32Job,
  254. PPROCESSINFO ppi)
  255. {
  256. PTHREADINFO pti;
  257. CheckCritIn();
  258. TAGMSG3(DBGTAG_Job, "SetProcessFlags: pW32Job %#p ppi %#p restrictions %#p",
  259. pW32Job, ppi, pW32Job->restrictions);
  260. UserAssert(ppi->pW32Job == pW32Job);
  261. if (pW32Job->restrictions == 0) {
  262. ((PW32PROCESS)ppi)->W32PF_Flags &= ~W32PF_RESTRICTED;
  263. } else {
  264. ((PW32PROCESS)ppi)->W32PF_Flags |= W32PF_RESTRICTED;
  265. }
  266. KeAttachProcess(PsGetProcessPcb(ppi->Process));
  267. /*
  268. * walk the pti list and set the restricted flag as appropriate
  269. */
  270. pti = ppi->ptiList;
  271. if (pW32Job->restrictions == 0) {
  272. while (pti) {
  273. try {
  274. pti->pClientInfo->dwTIFlags &= ~TIF_RESTRICTED;
  275. } except (W32ExceptionHandler(TRUE, RIP_WARNING)) {
  276. continue;
  277. }
  278. pti->TIF_flags &= ~TIF_RESTRICTED;
  279. pti = pti->ptiSibling;
  280. }
  281. } else {
  282. while (pti) {
  283. try {
  284. pti->pClientInfo->dwTIFlags |= TIF_RESTRICTED;
  285. } except (W32ExceptionHandler(TRUE, RIP_WARNING)) {
  286. continue;
  287. }
  288. pti->TIF_flags |= TIF_RESTRICTED;
  289. pti = pti->ptiSibling;
  290. }
  291. }
  292. KeDetachProcess();
  293. }
  294. /***************************************************************************\
  295. * JobCalloutAddProcess
  296. *
  297. * History:
  298. * 30-Jul-1997 CLupu Created.
  299. \***************************************************************************/
  300. BOOL JobCalloutAddProcess(
  301. PW32JOB pW32Job,
  302. PPROCESSINFO ppi)
  303. {
  304. PPROCESSINFO* ppiTable;
  305. CheckCritIn();
  306. UserAssert(pW32Job != NULL);
  307. /*
  308. * This process is not yet initialized
  309. */
  310. if (ppi->Process == NULL) {
  311. return FALSE;
  312. }
  313. if (!(ppi->W32PF_Flags & W32PF_PROCESSCONNECTED)) {
  314. TAGMSG2(DBGTAG_Job, "JobCalloutAddProcess: pW32Job %#p ppi %#p not yet initialized",
  315. pW32Job, ppi);
  316. return FALSE;
  317. }
  318. TAGMSG2(DBGTAG_Job, "JobCalloutAddProcess: pW32Job %#p ppi %#p",
  319. pW32Job, ppi);
  320. #if DBG
  321. /*
  322. * Make sure the process is not already in the job's process list
  323. */
  324. {
  325. UINT ip;
  326. for (ip = 0; ip < pW32Job->uProcessCount; ip++) {
  327. UserAssert(pW32Job->ppiTable[ip]->pW32Job == pW32Job);
  328. UserAssert(ppi != pW32Job->ppiTable[ip]);
  329. }
  330. }
  331. #endif // DBG
  332. /*
  333. * save the pW32Job pointer in the process info
  334. */
  335. UserAssert(ppi->pW32Job == NULL);
  336. ppi->pW32Job = pW32Job;
  337. if (pW32Job->uProcessCount == pW32Job->uMaxProcesses) {
  338. /*
  339. * No more room. Allocate more space for the process table
  340. */
  341. if (pW32Job->uMaxProcesses == 0) {
  342. UserAssert(pW32Job->ppiTable == NULL);
  343. ppiTable = UserAllocPool(JP_DELTA * sizeof(PPROCESSINFO), TAG_W32JOBEXTRA);
  344. } else {
  345. UserAssert(pW32Job->ppiTable != NULL);
  346. ppiTable = UserReAllocPool(pW32Job->ppiTable,
  347. pW32Job->uMaxProcesses * sizeof(PPROCESSINFO),
  348. (pW32Job->uMaxProcesses + JP_DELTA) * sizeof(PPROCESSINFO),
  349. TAG_W32JOBEXTRA);
  350. }
  351. if (ppiTable == NULL) {
  352. RIPMSG0(RIP_ERROR, "JobCalloutAddProcess: memory allocation error\n");
  353. return FALSE;
  354. }
  355. pW32Job->ppiTable = ppiTable;
  356. pW32Job->uMaxProcesses += JP_DELTA;
  357. }
  358. /*
  359. * now add the process to the job
  360. */
  361. pW32Job->ppiTable[pW32Job->uProcessCount] = ppi;
  362. (pW32Job->uProcessCount)++;
  363. SetProcessFlags(pW32Job, ppi);
  364. return TRUE;
  365. }
  366. /***************************************************************************\
  367. * JobCalloutTerminate
  368. *
  369. * This is called during the job object delete routine.
  370. *
  371. * History:
  372. * 30-Jul-1997 CLupu Created.
  373. \***************************************************************************/
  374. BOOL JobCalloutTerminate(
  375. PW32JOB pW32Job)
  376. {
  377. CheckCritIn();
  378. UserAssert(pW32Job != NULL);
  379. TAGMSG1(DBGTAG_Job, "JobCalloutTerminate: pW32Job %#p", pW32Job);
  380. /*
  381. * No processes should be attached to this job
  382. */
  383. UserAssert(pW32Job->ppiTable == NULL);
  384. UserAssert(pW32Job->uProcessCount == 0);
  385. UserAssert(pW32Job->uMaxProcesses == 0);
  386. if (pW32Job->pgh) {
  387. UserAssert(pW32Job->ughCrt > 0);
  388. UserAssert(pW32Job->ughMax > 0);
  389. UserFreePool(pW32Job->pgh);
  390. pW32Job->pgh = NULL;
  391. pW32Job->ughCrt = 0;
  392. pW32Job->ughMax = 0;
  393. }
  394. /*
  395. * remove the W32 job from the job's list
  396. */
  397. REMOVE_FROM_LIST(W32JOB, gpJobsList, pW32Job, pNext);
  398. RtlDestroyAtomTable(pW32Job->pAtomTable);
  399. UserFreePool(pW32Job);
  400. return TRUE;
  401. }