Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenjob.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS kernel 00004 * FILE: ntoskrnl/ps/job.c 00005 * PURPOSE: Job Native Functions 00006 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) (stubs) 00007 * Thomas Weidenmueller <w3seek@reactos.com> 00008 */ 00009 00010 /* INCLUDES *****************************************************************/ 00011 00012 #include <ntoskrnl.h> 00013 #define NDEBUG 00014 #include <debug.h> 00015 00016 00017 /* GLOBALS *******************************************************************/ 00018 00019 POBJECT_TYPE PsJobType = NULL; 00020 00021 LIST_ENTRY PsJobListHead; 00022 static FAST_MUTEX PsJobListLock; 00023 00024 BOOLEAN PspUseJobSchedulingClasses; 00025 00026 CHAR PspJobSchedulingClasses[PSP_JOB_SCHEDULING_CLASSES] = 00027 { 00028 1 * 6, 00029 2 * 6, 00030 3 * 6, 00031 4 * 6, 00032 5 * 6, 00033 6 * 6, 00034 7 * 6, 00035 8 * 6, 00036 9 * 6, 00037 10 * 6 00038 }; 00039 00040 GENERIC_MAPPING PspJobMapping = 00041 { 00042 STANDARD_RIGHTS_READ | JOB_OBJECT_QUERY, 00043 STANDARD_RIGHTS_WRITE | JOB_OBJECT_ASSIGN_PROCESS | JOB_OBJECT_SET_ATTRIBUTES | JOB_OBJECT_TERMINATE | JOB_OBJECT_SET_SECURITY_ATTRIBUTES, 00044 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE, 00045 STANDARD_RIGHTS_ALL | JOB_OBJECT_ALL_ACCESS 00046 }; 00047 00048 /* FUNCTIONS *****************************************************************/ 00049 00050 VOID 00051 NTAPI 00052 PspDeleteJob ( PVOID ObjectBody ) 00053 { 00054 PEJOB Job = (PEJOB)ObjectBody; 00055 00056 /* remove the reference to the completion port if associated */ 00057 if(Job->CompletionPort != NULL) 00058 { 00059 ObDereferenceObject(Job->CompletionPort); 00060 } 00061 00062 /* unlink the job object */ 00063 if(Job->JobLinks.Flink != NULL) 00064 { 00065 ExAcquireFastMutex(&PsJobListLock); 00066 RemoveEntryList(&Job->JobLinks); 00067 ExReleaseFastMutex(&PsJobListLock); 00068 } 00069 00070 ExDeleteResource(&Job->JobLock); 00071 } 00072 00073 VOID 00074 NTAPI 00075 INIT_FUNCTION 00076 PspInitializeJobStructures(VOID) 00077 { 00078 InitializeListHead(&PsJobListHead); 00079 ExInitializeFastMutex(&PsJobListLock); 00080 } 00081 00082 NTSTATUS 00083 NTAPI 00084 PspAssignProcessToJob(PEPROCESS Process, 00085 PEJOB Job) 00086 { 00087 DPRINT("PspAssignProcessToJob() is unimplemented!\n"); 00088 return STATUS_NOT_IMPLEMENTED; 00089 } 00090 00091 NTSTATUS 00092 NTAPI 00093 PspTerminateJobObject(PEJOB Job, 00094 KPROCESSOR_MODE AccessMode, 00095 NTSTATUS ExitStatus ) 00096 { 00097 DPRINT("PspTerminateJobObject() is unimplemented!\n"); 00098 return STATUS_NOT_IMPLEMENTED; 00099 } 00100 00101 VOID 00102 NTAPI 00103 PspRemoveProcessFromJob(IN PEPROCESS Process, 00104 IN PEJOB Job) 00105 { 00106 /* FIXME */ 00107 } 00108 00109 VOID 00110 NTAPI 00111 PspExitProcessFromJob(IN PEJOB Job, 00112 IN PEPROCESS Process) 00113 { 00114 /* FIXME */ 00115 } 00116 00117 /* 00118 * @unimplemented 00119 */ 00120 NTSTATUS 00121 NTAPI 00122 NtAssignProcessToJobObject ( 00123 HANDLE JobHandle, 00124 HANDLE ProcessHandle) 00125 { 00126 PEPROCESS Process; 00127 KPROCESSOR_MODE PreviousMode; 00128 NTSTATUS Status; 00129 00130 PAGED_CODE(); 00131 00132 PreviousMode = ExGetPreviousMode(); 00133 00134 /* make sure we're having a handle with enough rights, especially the to 00135 terminate the process. otherwise one could abuse the job objects to 00136 terminate processes without having rights granted to do so! The reason 00137 I open the process handle before the job handle is that a simple test showed 00138 that it first complains about a invalid process handle! The other way around 00139 would be simpler though... */ 00140 Status = ObReferenceObjectByHandle( 00141 ProcessHandle, 00142 PROCESS_TERMINATE, 00143 PsProcessType, 00144 PreviousMode, 00145 (PVOID*)&Process, 00146 NULL); 00147 if(NT_SUCCESS(Status)) 00148 { 00149 if(Process->Job == NULL) 00150 { 00151 PEJOB Job; 00152 00153 Status = ObReferenceObjectByHandle( 00154 JobHandle, 00155 JOB_OBJECT_ASSIGN_PROCESS, 00156 PsJobType, 00157 PreviousMode, 00158 (PVOID*)&Job, 00159 NULL); 00160 if(NT_SUCCESS(Status)) 00161 { 00162 /* lock the process so we can safely assign the process. Note that in the 00163 meanwhile another thread could have assigned this process to a job! */ 00164 00165 ExAcquireRundownProtection(&Process->RundownProtect); 00166 if(NT_SUCCESS(Status)) 00167 { 00168 // FIXME: This is broken 00169 if(Process->Job == NULL && PtrToUlong(Process->Session) == Job->SessionId) 00170 { 00171 /* Just store the pointer to the job object in the process, we'll 00172 assign it later. The reason we can't do this here is that locking 00173 the job object might require it to wait, which is a bad thing 00174 while holding the process lock! */ 00175 Process->Job = Job; 00176 } 00177 else 00178 { 00179 /* process is already assigned to a job or session id differs! */ 00180 Status = STATUS_ACCESS_DENIED; 00181 } 00182 ExReleaseRundownProtection(&Process->RundownProtect); 00183 00184 if(NT_SUCCESS(Status)) 00185 { 00186 /* let's actually assign the process to the job as we're not holding 00187 the process lock anymore! */ 00188 Status = PspAssignProcessToJob(Process, Job); 00189 } 00190 } 00191 00192 ObDereferenceObject(Job); 00193 } 00194 } 00195 else 00196 { 00197 /* process is already assigned to a job or session id differs! */ 00198 Status = STATUS_ACCESS_DENIED; 00199 } 00200 00201 ObDereferenceObject(Process); 00202 } 00203 00204 return Status; 00205 } 00206 00207 NTSTATUS 00208 NTAPI 00209 NtCreateJobSet(IN ULONG NumJob, 00210 IN PJOB_SET_ARRAY UserJobSet, 00211 IN ULONG Flags) 00212 { 00213 UNIMPLEMENTED; 00214 return STATUS_NOT_IMPLEMENTED; 00215 } 00216 00217 /* 00218 * @unimplemented 00219 */ 00220 NTSTATUS 00221 NTAPI 00222 NtCreateJobObject ( 00223 PHANDLE JobHandle, 00224 ACCESS_MASK DesiredAccess, 00225 POBJECT_ATTRIBUTES ObjectAttributes ) 00226 { 00227 HANDLE hJob; 00228 PEJOB Job; 00229 KPROCESSOR_MODE PreviousMode; 00230 PEPROCESS CurrentProcess; 00231 NTSTATUS Status; 00232 00233 PAGED_CODE(); 00234 00235 PreviousMode = ExGetPreviousMode(); 00236 CurrentProcess = PsGetCurrentProcess(); 00237 00238 /* check for valid buffers */ 00239 if (PreviousMode != KernelMode) 00240 { 00241 _SEH2_TRY 00242 { 00243 ProbeForWriteHandle(JobHandle); 00244 } 00245 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00246 { 00247 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 00248 } 00249 _SEH2_END; 00250 } 00251 00252 Status = ObCreateObject(PreviousMode, 00253 PsJobType, 00254 ObjectAttributes, 00255 PreviousMode, 00256 NULL, 00257 sizeof(EJOB), 00258 0, 00259 0, 00260 (PVOID*)&Job); 00261 00262 if(NT_SUCCESS(Status)) 00263 { 00264 /* FIXME - Zero all fields as we don't yet implement all of them */ 00265 RtlZeroMemory(Job, sizeof(EJOB)); 00266 00267 /* make sure that early destruction doesn't attempt to remove the object from 00268 the list before it even gets added! */ 00269 Job->JobLinks.Flink = NULL; 00270 00271 /* setup the job object */ 00272 InitializeListHead(&Job->ProcessListHead); 00273 Job->SessionId = PtrToUlong(CurrentProcess->Session); /* inherit the session id from the caller, FIXME: broken */ 00274 00275 Status = ExInitializeResource(&Job->JobLock); 00276 if(!NT_SUCCESS(Status)) 00277 { 00278 DPRINT1("Failed to initialize job lock!!!\n"); 00279 ObDereferenceObject(Job); 00280 return Status; 00281 } 00282 KeInitializeEvent(&Job->Event, NotificationEvent, FALSE); 00283 00284 /* link the object into the global job list */ 00285 ExAcquireFastMutex(&PsJobListLock); 00286 InsertTailList(&PsJobListHead, &Job->JobLinks); 00287 ExReleaseFastMutex(&PsJobListLock); 00288 00289 Status = ObInsertObject(Job, 00290 NULL, 00291 DesiredAccess, 00292 0, 00293 NULL, 00294 &hJob); 00295 if(NT_SUCCESS(Status)) 00296 { 00297 /* pass the handle back to the caller */ 00298 _SEH2_TRY 00299 { 00300 /* NOTE: if the caller passed invalid buffers to receive the handle it's his 00301 own fault! the object will still be created and live... It's possible 00302 to find the handle using ObFindHandleForObject()! */ 00303 *JobHandle = hJob; 00304 } 00305 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00306 { 00307 Status = _SEH2_GetExceptionCode(); 00308 } 00309 _SEH2_END; 00310 } 00311 } 00312 00313 return Status; 00314 } 00315 00316 00317 /* 00318 * @implemented 00319 */ 00320 NTSTATUS 00321 NTAPI 00322 NtIsProcessInJob ( 00323 IN HANDLE ProcessHandle, 00324 IN HANDLE JobHandle OPTIONAL ) 00325 { 00326 KPROCESSOR_MODE PreviousMode; 00327 PEPROCESS Process; 00328 NTSTATUS Status; 00329 00330 PreviousMode = ExGetPreviousMode(); 00331 00332 PAGED_CODE(); 00333 00334 Status = ObReferenceObjectByHandle( 00335 ProcessHandle, 00336 PROCESS_QUERY_INFORMATION, 00337 PsProcessType, 00338 PreviousMode, 00339 (PVOID*)&Process, 00340 NULL); 00341 if(NT_SUCCESS(Status)) 00342 { 00343 /* FIXME - make sure the job object doesn't get exchanged or deleted while trying to 00344 reference it, e.g. by locking it somehow until it is referenced... */ 00345 00346 PEJOB ProcessJob = Process->Job; 00347 00348 if(ProcessJob != NULL) 00349 { 00350 if(JobHandle == NULL) 00351 { 00352 /* the process is assigned to a job */ 00353 Status = STATUS_PROCESS_IN_JOB; 00354 } 00355 else /* JobHandle != NULL */ 00356 { 00357 PEJOB JobObject; 00358 00359 /* get the job object and compare the object pointer with the one assigned to the process */ 00360 Status = ObReferenceObjectByHandle(JobHandle, 00361 JOB_OBJECT_QUERY, 00362 PsJobType, 00363 PreviousMode, 00364 (PVOID*)&JobObject, 00365 NULL); 00366 if(NT_SUCCESS(Status)) 00367 { 00368 Status = ((ProcessJob == JobObject) ? STATUS_PROCESS_IN_JOB : STATUS_PROCESS_NOT_IN_JOB); 00369 ObDereferenceObject(JobObject); 00370 } 00371 } 00372 } 00373 else 00374 { 00375 /* the process is not assigned to any job */ 00376 Status = STATUS_PROCESS_NOT_IN_JOB; 00377 } 00378 ObDereferenceObject(Process); 00379 } 00380 00381 return Status; 00382 } 00383 00384 00385 /* 00386 * @implemented 00387 */ 00388 NTSTATUS 00389 NTAPI 00390 NtOpenJobObject ( 00391 PHANDLE JobHandle, 00392 ACCESS_MASK DesiredAccess, 00393 POBJECT_ATTRIBUTES ObjectAttributes) 00394 { 00395 KPROCESSOR_MODE PreviousMode; 00396 HANDLE hJob; 00397 NTSTATUS Status; 00398 00399 PAGED_CODE(); 00400 00401 PreviousMode = ExGetPreviousMode(); 00402 00403 /* check for valid buffers */ 00404 if (PreviousMode != KernelMode) 00405 { 00406 _SEH2_TRY 00407 { 00408 ProbeForWriteHandle(JobHandle); 00409 } 00410 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00411 { 00412 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 00413 } 00414 _SEH2_END; 00415 } 00416 00417 Status = ObOpenObjectByName(ObjectAttributes, 00418 PsJobType, 00419 PreviousMode, 00420 NULL, 00421 DesiredAccess, 00422 NULL, 00423 &hJob); 00424 if(NT_SUCCESS(Status)) 00425 { 00426 _SEH2_TRY 00427 { 00428 *JobHandle = hJob; 00429 } 00430 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00431 { 00432 Status = _SEH2_GetExceptionCode(); 00433 } 00434 _SEH2_END; 00435 } 00436 00437 return Status; 00438 } 00439 00440 00441 /* 00442 * @unimplemented 00443 */ 00444 NTSTATUS 00445 NTAPI 00446 NtQueryInformationJobObject ( 00447 HANDLE JobHandle, 00448 JOBOBJECTINFOCLASS JobInformationClass, 00449 PVOID JobInformation, 00450 ULONG JobInformationLength, 00451 PULONG ReturnLength ) 00452 { 00453 UNIMPLEMENTED; 00454 return STATUS_NOT_IMPLEMENTED; 00455 } 00456 00457 00458 /* 00459 * @unimplemented 00460 */ 00461 NTSTATUS 00462 NTAPI 00463 NtSetInformationJobObject ( 00464 HANDLE JobHandle, 00465 JOBOBJECTINFOCLASS JobInformationClass, 00466 PVOID JobInformation, 00467 ULONG JobInformationLength) 00468 { 00469 UNIMPLEMENTED; 00470 return STATUS_NOT_IMPLEMENTED; 00471 } 00472 00473 00474 /* 00475 * @unimplemented 00476 */ 00477 NTSTATUS 00478 NTAPI 00479 NtTerminateJobObject ( 00480 HANDLE JobHandle, 00481 NTSTATUS ExitStatus ) 00482 { 00483 KPROCESSOR_MODE PreviousMode; 00484 PEJOB Job; 00485 NTSTATUS Status; 00486 00487 PAGED_CODE(); 00488 00489 PreviousMode = ExGetPreviousMode(); 00490 00491 Status = ObReferenceObjectByHandle( 00492 JobHandle, 00493 JOB_OBJECT_TERMINATE, 00494 PsJobType, 00495 PreviousMode, 00496 (PVOID*)&Job, 00497 NULL); 00498 if(NT_SUCCESS(Status)) 00499 { 00500 Status = PspTerminateJobObject( 00501 Job, 00502 PreviousMode, 00503 ExitStatus); 00504 ObDereferenceObject(Job); 00505 } 00506 00507 return Status; 00508 } 00509 00510 00511 /* 00512 * @implemented 00513 */ 00514 PVOID 00515 NTAPI 00516 PsGetJobLock ( PEJOB Job ) 00517 { 00518 ASSERT(Job); 00519 return (PVOID)&Job->JobLock; 00520 } 00521 00522 00523 /* 00524 * @implemented 00525 */ 00526 PVOID 00527 NTAPI 00528 PsGetJobSessionId ( PEJOB Job ) 00529 { 00530 ASSERT(Job); 00531 return (PVOID)Job->SessionId; 00532 } 00533 00534 00535 /* 00536 * @implemented 00537 */ 00538 ULONG 00539 NTAPI 00540 PsGetJobUIRestrictionsClass ( PEJOB Job ) 00541 { 00542 ASSERT(Job); 00543 return Job->UIRestrictionsClass; 00544 } 00545 00546 00547 /* 00548 * @unimplemented 00549 */ 00550 VOID 00551 NTAPI 00552 PsSetJobUIRestrictionsClass(PEJOB Job, 00553 ULONG UIRestrictionsClass) 00554 { 00555 ASSERT(Job); 00556 (void)InterlockedExchangeUL(&Job->UIRestrictionsClass, UIRestrictionsClass); 00557 /* FIXME - walk through the job process list and update the restrictions? */ 00558 } 00559 00560 /* EOF */ Generated on Thu May 24 2012 04:24:44 for ReactOS by
1.7.6.1
|