ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

job.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.