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

process.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS Kernel
00003  * LICENSE:         GPL - See COPYING in the top level directory
00004  * FILE:            ntoskrnl/ps/process.c
00005  * PURPOSE:         Process Manager: Process Management
00006  * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
00007  *                  Thomas Weidenmueller (w3seek@reactos.org
00008  */
00009 
00010 /* INCLUDES ******************************************************************/
00011 
00012 #include <ntoskrnl.h>
00013 #define NDEBUG
00014 #include <debug.h>
00015 
00016 /* GLOBALS *******************************************************************/
00017 
00018 extern ULONG PsMinimumWorkingSet, PsMaximumWorkingSet;
00019 
00020 POBJECT_TYPE PsProcessType = NULL;
00021 
00022 LIST_ENTRY PsActiveProcessHead;
00023 KGUARDED_MUTEX PspActiveProcessMutex;
00024 
00025 LARGE_INTEGER ShortPsLockDelay;
00026 
00027 ULONG PsRawPrioritySeparation = 0;
00028 ULONG PsPrioritySeparation;
00029 CHAR PspForegroundQuantum[3];
00030 
00031 /* Fixed quantum table */
00032 CHAR PspFixedQuantums[6] =
00033 {
00034     /* Short quantums */
00035     3 * 6, /* Level 1 */
00036     3 * 6, /* Level 2 */
00037     3 * 6, /* Level 3 */
00038 
00039     /* Long quantums */
00040     6 * 6, /* Level 1 */
00041     6 * 6, /* Level 2 */
00042     6 * 6  /* Level 3 */
00043 };
00044 
00045 /* Variable quantum table */
00046 CHAR PspVariableQuantums[6] =
00047 {
00048     /* Short quantums */
00049     1 * 6, /* Level 1 */
00050     2 * 6, /* Level 2 */
00051     3 * 6, /* Level 3 */
00052 
00053     /* Long quantums */
00054     2 * 6, /* Level 1 */
00055     4 * 6, /* Level 2 */
00056     6 * 6  /* Level 3 */
00057 };
00058 
00059 /* Priority table */
00060 KPRIORITY PspPriorityTable[PROCESS_PRIORITY_CLASS_ABOVE_NORMAL + 1] =
00061 {
00062     8,
00063     4,
00064     8,
00065     13,
00066     24,
00067     6,
00068     10
00069 };
00070 
00071 /* PRIVATE FUNCTIONS *********************************************************/
00072 
00073 PETHREAD
00074 NTAPI
00075 PsGetNextProcessThread(IN PEPROCESS Process,
00076                        IN PETHREAD Thread OPTIONAL)
00077 {
00078     PETHREAD FoundThread = NULL;
00079     PLIST_ENTRY ListHead, Entry;
00080     PAGED_CODE();
00081     PSTRACE(PS_PROCESS_DEBUG,
00082             "Process: %p Thread: %p\n", Process, Thread);
00083 
00084     /* Lock the process */
00085     KeEnterCriticalRegion();
00086     ExAcquirePushLockShared(&Process->ProcessLock);
00087 
00088     /* Check if we're already starting somewhere */
00089     if (Thread)
00090     {
00091         /* Start where we left off */
00092         Entry = Thread->ThreadListEntry.Flink;
00093     }
00094     else
00095     {
00096         /* Start at the beginning */
00097         Entry = Process->ThreadListHead.Flink;
00098     }
00099 
00100     /* Set the list head and start looping */
00101     ListHead = &Process->ThreadListHead;
00102     while (ListHead != Entry)
00103     {
00104         /* Get the Thread */
00105         FoundThread = CONTAINING_RECORD(Entry, ETHREAD, ThreadListEntry);
00106 
00107         /* Safe reference the thread */
00108         if (ObReferenceObjectSafe(FoundThread)) break;
00109 
00110         /* Nothing found, keep looping */
00111         FoundThread = NULL;
00112         Entry = Entry->Flink;
00113     }
00114 
00115     /* Unlock the process */
00116     ExReleasePushLockShared(&Process->ProcessLock);
00117     KeLeaveCriticalRegion();
00118 
00119     /* Check if we had a starting thread, and dereference it */
00120     if (Thread) ObDereferenceObject(Thread);
00121 
00122     /* Return what we found */
00123     return FoundThread;
00124 }
00125 
00126 PEPROCESS
00127 NTAPI
00128 PsGetNextProcess(IN PEPROCESS OldProcess)
00129 {
00130     PLIST_ENTRY Entry;
00131     PEPROCESS FoundProcess = NULL;
00132     PAGED_CODE();
00133     PSTRACE(PS_PROCESS_DEBUG, "Process: %p\n", OldProcess);
00134 
00135     /* Acquire the Active Process Lock */
00136     KeAcquireGuardedMutex(&PspActiveProcessMutex);
00137 
00138     /* Check if we're already starting somewhere */
00139     if (OldProcess)
00140     {
00141         /* Start where we left off */
00142         Entry = OldProcess->ActiveProcessLinks.Flink;
00143     }
00144     else
00145     {
00146         /* Start at the beginning */
00147         Entry = PsActiveProcessHead.Flink;
00148     }
00149 
00150     /* Loop the process list */
00151     while (Entry != &PsActiveProcessHead)
00152     {
00153         /* Get the process */
00154         FoundProcess = CONTAINING_RECORD(Entry, EPROCESS, ActiveProcessLinks);
00155 
00156         /* Reference the process */
00157         if (ObReferenceObjectSafe(FoundProcess)) break;
00158 
00159         /* Nothing found, keep trying */
00160         FoundProcess = NULL;
00161         Entry = Entry->Flink;
00162     }
00163 
00164     /* Release the lock */
00165     KeReleaseGuardedMutex(&PspActiveProcessMutex);
00166 
00167     /* Dereference the Process we had referenced earlier */
00168     if (OldProcess) ObDereferenceObject(OldProcess);
00169     return FoundProcess;
00170 }
00171 
00172 KPRIORITY
00173 NTAPI
00174 PspComputeQuantumAndPriority(IN PEPROCESS Process,
00175                              IN PSPROCESSPRIORITYMODE Mode,
00176                              OUT PUCHAR Quantum)
00177 {
00178     ULONG i;
00179     UCHAR LocalQuantum, MemoryPriority;
00180     PAGED_CODE();
00181     PSTRACE(PS_PROCESS_DEBUG, "Process: %p Mode: %lx\n", Process, Mode);
00182 
00183     /* Check if this is a foreground process */
00184     if (Mode == PsProcessPriorityForeground)
00185     {
00186         /* Set the memory priority and use priority separation */
00187         MemoryPriority = MEMORY_PRIORITY_FOREGROUND;
00188         i = PsPrioritySeparation;
00189     }
00190     else
00191     {
00192         /* Set the background memory priority and no separation */
00193         MemoryPriority = MEMORY_PRIORITY_BACKGROUND;
00194         i = 0;
00195     }
00196 
00197     /* Make sure that the process mode isn't spinning */
00198     if (Mode != PsProcessPrioritySpinning)
00199     {
00200         /* Set the priority */
00201         MmSetMemoryPriorityProcess(Process, MemoryPriority);
00202     }
00203 
00204     /* Make sure that the process isn't idle */
00205     if (Process->PriorityClass != PROCESS_PRIORITY_CLASS_IDLE)
00206     {
00207         /* Does the process have a job? */
00208         if ((Process->Job) && (PspUseJobSchedulingClasses))
00209         {
00210             /* Use job quantum */
00211             LocalQuantum = PspJobSchedulingClasses[Process->Job->
00212                                                    SchedulingClass];
00213         }
00214         else
00215         {
00216             /* Use calculated quantum */
00217             LocalQuantum = PspForegroundQuantum[i];
00218         }
00219     }
00220     else
00221     {
00222         /* Process is idle, use default quantum */
00223         LocalQuantum = 6;
00224     }
00225 
00226     /* Return quantum to caller */
00227     *Quantum = LocalQuantum;
00228 
00229     /* Return priority */
00230     return PspPriorityTable[Process->PriorityClass];
00231 }
00232 
00233 VOID
00234 NTAPI
00235 PsChangeQuantumTable(IN BOOLEAN Immediate,
00236                      IN ULONG PrioritySeparation)
00237 {
00238     PEPROCESS Process = NULL;
00239     ULONG i;
00240     UCHAR Quantum;
00241     PCHAR QuantumTable;
00242     PAGED_CODE();
00243     PSTRACE(PS_PROCESS_DEBUG,
00244             "%lx PrioritySeparation: %lx\n", Immediate, PrioritySeparation);
00245 
00246     /* Write the current priority separation */
00247     PsPrioritySeparation = PspPrioritySeparationFromMask(PrioritySeparation);
00248 
00249     /* Normalize it if it was too high */
00250     if (PsPrioritySeparation == 3) PsPrioritySeparation = 2;
00251 
00252     /* Get the quantum table to use */
00253     if (PspQuantumTypeFromMask(PrioritySeparation) == PSP_VARIABLE_QUANTUMS)
00254     {
00255         /* Use a variable table */
00256         QuantumTable = PspVariableQuantums;
00257     }
00258     else
00259     {
00260         /* Use fixed table */
00261         QuantumTable = PspFixedQuantums;
00262     }
00263 
00264     /* Now check if we should use long or short */
00265     if (PspQuantumLengthFromMask(PrioritySeparation) == PSP_LONG_QUANTUMS)
00266     {
00267         /* Use long quantums */
00268         QuantumTable += 3;
00269     }
00270 
00271     /* Check if we're using long fixed quantums */
00272     if (QuantumTable == &PspFixedQuantums[3])
00273     {
00274         /* Use Job scheduling classes */
00275          PspUseJobSchedulingClasses = TRUE;
00276     }
00277     else
00278     {
00279         /* Otherwise, we don't */
00280         PspUseJobSchedulingClasses = FALSE;
00281     }
00282 
00283     /* Copy the selected table into the Foreground Quantum table */
00284     RtlCopyMemory(PspForegroundQuantum,
00285                   QuantumTable,
00286                   sizeof(PspForegroundQuantum));
00287 
00288     /* Check if we should apply these changes real-time */
00289     if (Immediate)
00290     {
00291         /* We are...loop every process */
00292         Process = PsGetNextProcess(Process);
00293         while (Process)
00294         {
00295             /*
00296              * Use the priority separation, unless the process has
00297              * low memory priority
00298              */
00299             i = (Process->Vm.Flags.MemoryPriority == 1) ?
00300                 0: PsPrioritySeparation;
00301 
00302             /* Make sure that the process isn't idle */
00303             if (Process->PriorityClass != PROCESS_PRIORITY_CLASS_IDLE)
00304             {
00305                 /* Does the process have a job? */
00306                 if ((Process->Job) && (PspUseJobSchedulingClasses))
00307                 {
00308                     /* Use job quantum */
00309                     Quantum = PspJobSchedulingClasses[Process->Job->
00310                                                       SchedulingClass];
00311                 }
00312                 else
00313                 {
00314                     /* Use calculated quantum */
00315                     Quantum = PspForegroundQuantum[i];
00316                 }
00317             }
00318             else
00319             {
00320                 /* Process is idle, use default quantum */
00321                 Quantum = 6;
00322             }
00323 
00324             /* Now set the quantum */
00325             KeSetQuantumProcess(&Process->Pcb, Quantum);
00326 
00327             /* Get the next process */
00328             Process = PsGetNextProcess(Process);
00329         }
00330     }
00331 }
00332 
00333 NTSTATUS
00334 NTAPI
00335 PspCreateProcess(OUT PHANDLE ProcessHandle,
00336                  IN ACCESS_MASK DesiredAccess,
00337                  IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
00338                  IN HANDLE ParentProcess OPTIONAL,
00339                  IN ULONG Flags,
00340                  IN HANDLE SectionHandle OPTIONAL,
00341                  IN HANDLE DebugPort OPTIONAL,
00342                  IN HANDLE ExceptionPort OPTIONAL,
00343                  IN BOOLEAN InJob)
00344 {
00345     HANDLE hProcess;
00346     PEPROCESS Process, Parent;
00347     PVOID ExceptionPortObject;
00348     PDEBUG_OBJECT DebugObject;
00349     PSECTION_OBJECT SectionObject;
00350     NTSTATUS Status, AccessStatus;
00351     ULONG_PTR DirectoryTableBase[2] = {0,0};
00352     KAFFINITY Affinity;
00353     HANDLE_TABLE_ENTRY CidEntry;
00354     PETHREAD CurrentThread = PsGetCurrentThread();
00355     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
00356     PEPROCESS CurrentProcess = PsGetCurrentProcess();
00357     ULONG MinWs, MaxWs;
00358     ACCESS_STATE LocalAccessState;
00359     PACCESS_STATE AccessState = &LocalAccessState;
00360     AUX_ACCESS_DATA AuxData;
00361     UCHAR Quantum;
00362     BOOLEAN Result, SdAllocated;
00363     PSECURITY_DESCRIPTOR SecurityDescriptor;
00364     SECURITY_SUBJECT_CONTEXT SubjectContext;
00365     BOOLEAN NeedsPeb = FALSE;
00366     INITIAL_PEB InitialPeb;
00367     PAGED_CODE();
00368     PSTRACE(PS_PROCESS_DEBUG,
00369             "ProcessHandle: %p Parent: %p\n", ProcessHandle, ParentProcess);
00370 
00371     /* Validate flags */
00372     if (Flags & ~PS_ALL_FLAGS) return STATUS_INVALID_PARAMETER;
00373 
00374     /* Check for parent */
00375     if (ParentProcess)
00376     {
00377         /* Reference it */
00378         Status = ObReferenceObjectByHandle(ParentProcess,
00379                                            PROCESS_CREATE_PROCESS,
00380                                            PsProcessType,
00381                                            PreviousMode,
00382                                            (PVOID*)&Parent,
00383                                            NULL);
00384         if (!NT_SUCCESS(Status)) return Status;
00385 
00386         /* If this process should be in a job but the parent isn't */
00387         if ((InJob) && (!Parent->Job))
00388         {
00389             /* This is illegal. Dereference the parent and fail */
00390             ObDereferenceObject(Parent);
00391             return STATUS_INVALID_PARAMETER;
00392         }
00393 
00394         /* Inherit Parent process's Affinity. */
00395         Affinity = Parent->Pcb.Affinity;
00396     }
00397     else
00398     {
00399         /* We have no parent */
00400         Parent = NULL;
00401         Affinity = KeActiveProcessors;
00402     }
00403 
00404     /* Save working set data */
00405     MinWs = PsMinimumWorkingSet;
00406     MaxWs = PsMaximumWorkingSet;
00407 
00408     /* Create the Object */
00409     Status = ObCreateObject(PreviousMode,
00410                             PsProcessType,
00411                             ObjectAttributes,
00412                             PreviousMode,
00413                             NULL,
00414                             sizeof(EPROCESS),
00415                             0,
00416                             0,
00417                             (PVOID*)&Process);
00418     if (!NT_SUCCESS(Status)) goto Cleanup;
00419 
00420     /* Clean up the Object */
00421     RtlZeroMemory(Process, sizeof(EPROCESS));
00422 
00423     /* Initialize pushlock and rundown protection */
00424     ExInitializeRundownProtection(&Process->RundownProtect);
00425     Process->ProcessLock.Value = 0;
00426 
00427     /* Setup the Thread List Head */
00428     InitializeListHead(&Process->ThreadListHead);
00429 
00430     /* Set up the Quota Block from the Parent */
00431     PspInheritQuota(Process, Parent);
00432 
00433     /* Set up Dos Device Map from the Parent */
00434     ObInheritDeviceMap(Parent, Process);
00435 
00436     /* Check if we have a parent */
00437     if (Parent)
00438     {
00439         /* Inherit PID and Hard Error Processing */
00440         Process->InheritedFromUniqueProcessId = Parent->UniqueProcessId;
00441         Process->DefaultHardErrorProcessing = Parent->
00442                                               DefaultHardErrorProcessing;
00443     }
00444     else
00445     {
00446         /* Use default hard error processing */
00447         Process->DefaultHardErrorProcessing = TRUE;
00448     }
00449 
00450     /* Check for a section handle */
00451     if (SectionHandle)
00452     {
00453         /* Get a pointer to it */
00454         Status = ObReferenceObjectByHandle(SectionHandle,
00455                                            SECTION_MAP_EXECUTE,
00456                                            MmSectionObjectType,
00457                                            PreviousMode,
00458                                            (PVOID*)&SectionObject,
00459                                            NULL);
00460         if (!NT_SUCCESS(Status)) goto CleanupWithRef;
00461     }
00462     else
00463     {
00464         /* Assume no section object */
00465         SectionObject = NULL;
00466 
00467         /* Is the parent the initial process?
00468          * Check for NULL also, as at initialization PsInitialSystemProcess is NULL */
00469         if (Parent != PsInitialSystemProcess && (Parent != NULL))
00470         {
00471             /* It's not, so acquire the process rundown */
00472             if (ExAcquireRundownProtection(&Parent->RundownProtect))
00473             {
00474                 /* If the parent has a section, use it */
00475                 SectionObject = Parent->SectionObject;
00476                 if (SectionObject) ObReferenceObject(SectionObject);
00477 
00478                 /* Release process rundown */
00479                 ExReleaseRundownProtection(&Parent->RundownProtect);
00480             }
00481 
00482             /* If we don't have a section object */
00483             if (!SectionObject)
00484             {
00485                 /* Then the process is in termination, so fail */
00486                 Status = STATUS_PROCESS_IS_TERMINATING;
00487                 goto CleanupWithRef;
00488             }
00489         }
00490     }
00491 
00492     /* Save the pointer to the section object */
00493     Process->SectionObject = SectionObject;
00494 
00495     /* Check for the debug port */
00496     if (DebugPort)
00497     {
00498         /* Reference it */
00499         Status = ObReferenceObjectByHandle(DebugPort,
00500                                            DEBUG_OBJECT_ADD_REMOVE_PROCESS,
00501                                            DbgkDebugObjectType,
00502                                            PreviousMode,
00503                                            (PVOID*)&DebugObject,
00504                                            NULL);
00505         if (!NT_SUCCESS(Status)) goto CleanupWithRef;
00506 
00507         /* Save the debug object */
00508         Process->DebugPort = DebugObject;
00509 
00510         /* Check if the caller doesn't want the debug stuff inherited */
00511         if (Flags & PS_NO_DEBUG_INHERIT)
00512         {
00513             /* Set the process flag */
00514             InterlockedOr((PLONG)&Process->Flags, PSF_NO_DEBUG_INHERIT_BIT);
00515         }
00516     }
00517     else
00518     {
00519         /* Do we have a parent? Copy his debug port */
00520         if (Parent) DbgkCopyProcessDebugPort(Process, Parent);
00521     }
00522 
00523     /* Now check for an exception port */
00524     if (ExceptionPort)
00525     {
00526         /* Reference it */
00527         Status = ObReferenceObjectByHandle(ExceptionPort,
00528                                            PORT_ALL_ACCESS,
00529                                            LpcPortObjectType,
00530                                            PreviousMode,
00531                                            (PVOID*)&ExceptionPortObject,
00532                                            NULL);
00533         if (!NT_SUCCESS(Status)) goto CleanupWithRef;
00534 
00535         /* Save the exception port */
00536         Process->ExceptionPort = ExceptionPortObject;
00537     }
00538 
00539     /* Save the pointer to the section object */
00540     Process->SectionObject = SectionObject;
00541 
00542     /* Set default exit code */
00543     Process->ExitStatus = STATUS_PENDING;
00544 
00545     /* Check if this is the initial process being built */
00546     if (Parent)
00547     {
00548         /* Create the address space for the child */
00549         if (!MmCreateProcessAddressSpace(MinWs,
00550                                          Process,
00551                                          DirectoryTableBase))
00552         {
00553             /* Failed */
00554             Status = STATUS_INSUFFICIENT_RESOURCES;
00555             goto CleanupWithRef;
00556         }
00557     }
00558     else
00559     {
00560         /* Otherwise, we are the boot process, we're already semi-initialized */
00561         Process->ObjectTable = CurrentProcess->ObjectTable;
00562         Status = MmInitializeHandBuiltProcess(Process, DirectoryTableBase);
00563         if (!NT_SUCCESS(Status)) goto CleanupWithRef;
00564     }
00565 
00566     /* We now have an address space */
00567     InterlockedOr((PLONG)&Process->Flags, PSF_HAS_ADDRESS_SPACE_BIT);
00568 
00569     /* Set the maximum WS */
00570     Process->Vm.MaximumWorkingSetSize = MaxWs;
00571 
00572     /* Now initialize the Kernel Process */
00573     KeInitializeProcess(&Process->Pcb,
00574                         PROCESS_PRIORITY_NORMAL,
00575                         Affinity,
00576                         DirectoryTableBase,
00577                         (BOOLEAN)(Process->DefaultHardErrorProcessing & 4));
00578 
00579     /* Duplicate Parent Token */
00580     Status = PspInitializeProcessSecurity(Process, Parent);
00581     if (!NT_SUCCESS(Status)) goto CleanupWithRef;
00582 
00583     /* Set default priority class */
00584     Process->PriorityClass = PROCESS_PRIORITY_CLASS_NORMAL;
00585 
00586     /* Check if we have a parent */
00587     if (Parent)
00588     {
00589         /* Check our priority class */
00590         if (Parent->PriorityClass == PROCESS_PRIORITY_CLASS_IDLE ||
00591             Parent->PriorityClass == PROCESS_PRIORITY_CLASS_BELOW_NORMAL)
00592         {
00593             /* Normalize it */
00594             Process->PriorityClass = Parent->PriorityClass;
00595         }
00596 
00597         /* Initialize object manager for the process */
00598         Status = ObInitProcess(Flags & PS_INHERIT_HANDLES ? Parent : NULL,
00599                                Process);
00600         if (!NT_SUCCESS(Status)) goto CleanupWithRef;
00601     }
00602     else
00603     {
00604         /* Do the second part of the boot process memory setup */
00605         Status = MmInitializeHandBuiltProcess2(Process);
00606         if (!NT_SUCCESS(Status)) goto CleanupWithRef;
00607     }
00608 
00609     /* Set success for now */
00610     Status = STATUS_SUCCESS;
00611 
00612     /* Check if this is a real user-mode process */
00613     if (SectionHandle)
00614     {
00615         /* Initialize the address space */
00616         Status = MmInitializeProcessAddressSpace(Process,
00617                                                  NULL,
00618                                                  SectionObject,
00619                                                  &Flags,
00620                                                  &Process->
00621                                                  SeAuditProcessCreationInfo.
00622                                                  ImageFileName);
00623         if (!NT_SUCCESS(Status)) goto CleanupWithRef;
00624 
00625         //
00626         // We need a PEB
00627         //
00628         NeedsPeb = TRUE;
00629     }
00630     else if (Parent)
00631     {
00632         /* Check if this is a child of the system process */
00633         if (Parent != PsInitialSystemProcess)
00634         {
00635             //
00636             // We need a PEB
00637             //
00638             NeedsPeb = TRUE;
00639 
00640             /* This is a clone! */
00641             ASSERTMSG("No support for cloning yet\n", FALSE);
00642         }
00643         else
00644         {
00645             /* This is the initial system process */
00646             Flags &= ~PS_LARGE_PAGES;
00647             Status = MmInitializeProcessAddressSpace(Process,
00648                                                      NULL,
00649                                                      NULL,
00650                                                      &Flags,
00651                                                      NULL);
00652             if (!NT_SUCCESS(Status)) goto CleanupWithRef;
00653 
00654             /* Create a dummy image file name */
00655             Process->SeAuditProcessCreationInfo.ImageFileName =
00656                 ExAllocatePoolWithTag(PagedPool,
00657                                       sizeof(OBJECT_NAME_INFORMATION),
00658                                       'aPeS');
00659             if (!Process->SeAuditProcessCreationInfo.ImageFileName)
00660             {
00661                 /* Fail */
00662                 Status = STATUS_INSUFFICIENT_RESOURCES;
00663                 goto CleanupWithRef;
00664             }
00665 
00666             /* Zero it out */
00667             RtlZeroMemory(Process->SeAuditProcessCreationInfo.ImageFileName,
00668                           sizeof(OBJECT_NAME_INFORMATION));
00669         }
00670     }
00671 
00672 #if MI_TRACE_PFNS
00673     /* Copy the process name now that we have it */
00674     memcpy(MiGetPfnEntry(Process->Pcb.DirectoryTableBase[0] >> PAGE_SHIFT)->ProcessName, Process->ImageFileName, 16);
00675     if (Process->Pcb.DirectoryTableBase[1]) memcpy(MiGetPfnEntry(Process->Pcb.DirectoryTableBase[1] >> PAGE_SHIFT)->ProcessName, Process->ImageFileName, 16);
00676     if (Process->WorkingSetPage) memcpy(MiGetPfnEntry(Process->WorkingSetPage)->ProcessName, Process->ImageFileName, 16);
00677 #endif
00678 
00679     /* Check if we have a section object and map the system DLL */
00680     if (SectionObject) PspMapSystemDll(Process, NULL, FALSE);
00681 
00682     /* Create a handle for the Process */
00683     CidEntry.Object = Process;
00684     CidEntry.GrantedAccess = 0;
00685     Process->UniqueProcessId = ExCreateHandle(PspCidTable, &CidEntry);
00686     if (!Process->UniqueProcessId)
00687     {
00688         /* Fail */
00689         Status = STATUS_INSUFFICIENT_RESOURCES;
00690         goto CleanupWithRef;
00691     }
00692 
00693     /* Set the handle table PID */
00694     Process->ObjectTable->UniqueProcessId = Process->UniqueProcessId;
00695 
00696     /* Check if we need to audit */
00697     if (SeDetailedAuditingWithToken(NULL)) SeAuditProcessCreate(Process);
00698 
00699     /* Check if the parent had a job */
00700     if ((Parent) && (Parent->Job))
00701     {
00702         /* FIXME: We need to insert this process */
00703         DPRINT1("Jobs not yet supported\n");
00704         ASSERT(FALSE);
00705     }
00706 
00707     /* Create PEB only for User-Mode Processes */
00708     if ((Parent) && (NeedsPeb))
00709     {
00710         //
00711         // Set up the initial PEB
00712         //
00713         RtlZeroMemory(&InitialPeb, sizeof(INITIAL_PEB));
00714         InitialPeb.Mutant = (HANDLE)-1;
00715         InitialPeb.ImageUsesLargePages = 0; // FIXME: Not yet supported
00716 
00717         //
00718         // Create it only if we have an image section
00719         //
00720         if (SectionHandle)
00721         {
00722             //
00723             // Create it
00724             //
00725             Status = MmCreatePeb(Process, &InitialPeb, &Process->Peb);
00726             if (!NT_SUCCESS(Status)) goto CleanupWithRef;
00727         }
00728         else
00729         {
00730             //
00731             // We have to clone it
00732             //
00733             ASSERTMSG("No support for cloning yet\n", FALSE);
00734         }
00735 
00736     }
00737 
00738     /* The process can now be activated */
00739     KeAcquireGuardedMutex(&PspActiveProcessMutex);
00740     InsertTailList(&PsActiveProcessHead, &Process->ActiveProcessLinks);
00741     KeReleaseGuardedMutex(&PspActiveProcessMutex);
00742 
00743     /* Create an access state */
00744     Status = SeCreateAccessStateEx(CurrentThread,
00745                                    ((Parent) &&
00746                                    (Parent == PsInitialSystemProcess)) ?
00747                                     Parent : CurrentProcess,
00748                                    &LocalAccessState,
00749                                    &AuxData,
00750                                    DesiredAccess,
00751                                    &PsProcessType->TypeInfo.GenericMapping);
00752     if (!NT_SUCCESS(Status)) goto CleanupWithRef;
00753 
00754     /* Insert the Process into the Object Directory */
00755     Status = ObInsertObject(Process,
00756                             AccessState,
00757                             DesiredAccess,
00758                             1,
00759                             NULL,
00760                             &hProcess);
00761 
00762     /* Free the access state */
00763     if (AccessState) SeDeleteAccessState(AccessState);
00764 
00765     /* Cleanup on failure */
00766     if (!NT_SUCCESS(Status)) goto Cleanup;
00767 
00768     /* Compute Quantum and Priority */
00769     ASSERT(IsListEmpty(&Process->ThreadListHead) == TRUE);
00770     Process->Pcb.BasePriority =
00771         (SCHAR)PspComputeQuantumAndPriority(Process,
00772                                             PsProcessPriorityBackground,
00773                                             &Quantum);
00774     Process->Pcb.QuantumReset = Quantum;
00775 
00776     /* Check if we have a parent other then the initial system process */
00777     Process->GrantedAccess = PROCESS_TERMINATE;
00778     if ((Parent) && (Parent != PsInitialSystemProcess))
00779     {
00780         /* Get the process's SD */
00781         Status = ObGetObjectSecurity(Process,
00782                                      &SecurityDescriptor,
00783                                      &SdAllocated);
00784         if (!NT_SUCCESS(Status))
00785         {
00786             /* We failed, close the handle and clean up */
00787             ObCloseHandle(hProcess, PreviousMode);
00788             goto CleanupWithRef;
00789         }
00790 
00791         /* Create the subject context */
00792         SubjectContext.ProcessAuditId = Process;
00793         SubjectContext.PrimaryToken = PsReferencePrimaryToken(Process);
00794         SubjectContext.ClientToken = NULL;
00795 
00796         /* Do the access check */
00797         Result = SeAccessCheck(SecurityDescriptor,
00798                                &SubjectContext,
00799                                FALSE,
00800                                MAXIMUM_ALLOWED,
00801                                0,
00802                                NULL,
00803                                &PsProcessType->TypeInfo.GenericMapping,
00804                                PreviousMode,
00805                                &Process->GrantedAccess,
00806                                &AccessStatus);
00807 
00808         /* Dereference the token and let go the SD */
00809         ObFastDereferenceObject(&Process->Token,
00810                                 SubjectContext.PrimaryToken);
00811         ObReleaseObjectSecurity(SecurityDescriptor, SdAllocated);
00812 
00813         /* Remove access if it failed */
00814         if (!Result) Process->GrantedAccess = 0;
00815 
00816         /* Give the process some basic access */
00817         Process->GrantedAccess |= (PROCESS_VM_OPERATION |
00818                                    PROCESS_VM_READ |
00819                                    PROCESS_VM_WRITE |
00820                                    PROCESS_QUERY_INFORMATION |
00821                                    PROCESS_TERMINATE |
00822                                    PROCESS_CREATE_THREAD |
00823                                    PROCESS_DUP_HANDLE |
00824                                    PROCESS_CREATE_PROCESS |
00825                                    PROCESS_SET_INFORMATION |
00826                                    STANDARD_RIGHTS_ALL |
00827                                    PROCESS_SET_QUOTA);
00828     }
00829     else
00830     {
00831         /* Set full granted access */
00832         Process->GrantedAccess = PROCESS_ALL_ACCESS;
00833     }
00834 
00835     /* Set the Creation Time */
00836     KeQuerySystemTime(&Process->CreateTime);
00837 
00838     /* Protect against bad user-mode pointer */
00839     _SEH2_TRY
00840     {
00841         /* Save the process handle */
00842        *ProcessHandle = hProcess;
00843     }
00844     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00845     {
00846         /* Get the exception code */
00847        Status = _SEH2_GetExceptionCode();
00848     }
00849     _SEH2_END;
00850 
00851     /* Run the Notification Routines */
00852     PspRunCreateProcessNotifyRoutines(Process, TRUE);
00853 
00854     /* If 12 processes have been created, enough of user-mode is ready */
00855     if (++ProcessCount == 12) Ki386PerfEnd();
00856 
00857 CleanupWithRef:
00858     /*
00859      * Dereference the process. For failures, kills the process and does
00860      * cleanup present in PspDeleteProcess. For success, kills the extra
00861      * reference added by ObInsertObject.
00862      */
00863     ObDereferenceObject(Process);
00864 
00865 Cleanup:
00866     /* Dereference the parent */
00867     if (Parent) ObDereferenceObject(Parent);
00868 
00869     /* Return status to caller */
00870     return Status;
00871 }
00872 
00873 /* PUBLIC FUNCTIONS **********************************************************/
00874 
00875 /*
00876  * @implemented
00877  */
00878 NTSTATUS
00879 NTAPI
00880 PsCreateSystemProcess(OUT PHANDLE ProcessHandle,
00881                       IN ACCESS_MASK DesiredAccess,
00882                       IN POBJECT_ATTRIBUTES ObjectAttributes)
00883 {
00884     /* Call the internal API */
00885     return PspCreateProcess(ProcessHandle,
00886                             DesiredAccess,
00887                             ObjectAttributes,
00888                             NULL,
00889                             0,
00890                             NULL,
00891                             NULL,
00892                             NULL,
00893                             FALSE);
00894 }
00895 
00896 /*
00897  * @implemented
00898  */
00899 NTSTATUS
00900 NTAPI
00901 PsLookupProcessByProcessId(IN HANDLE ProcessId,
00902                            OUT PEPROCESS *Process)
00903 {
00904     PHANDLE_TABLE_ENTRY CidEntry;
00905     PEPROCESS FoundProcess;
00906     NTSTATUS Status = STATUS_INVALID_PARAMETER;
00907     PAGED_CODE();
00908     PSTRACE(PS_PROCESS_DEBUG, "ProcessId: %p\n", ProcessId);
00909     KeEnterCriticalRegion();
00910 
00911     /* Get the CID Handle Entry */
00912     CidEntry = ExMapHandleToPointer(PspCidTable, ProcessId);
00913     if (CidEntry)
00914     {
00915         /* Get the Process */
00916         FoundProcess = CidEntry->Object;
00917 
00918         /* Make sure it's really a process */
00919         if (FoundProcess->Pcb.Header.Type == ProcessObject)
00920         {
00921             /* Safe Reference and return it */
00922             if (ObReferenceObjectSafe(FoundProcess))
00923             {
00924                 *Process = FoundProcess;
00925                 Status = STATUS_SUCCESS;
00926             }
00927         }
00928 
00929         /* Unlock the Entry */
00930         ExUnlockHandleTableEntry(PspCidTable, CidEntry);
00931     }
00932 
00933     /* Return to caller */
00934     KeLeaveCriticalRegion();
00935     return Status;
00936 }
00937 
00938 /*
00939  * @implemented
00940  */
00941 NTSTATUS
00942 NTAPI
00943 PsLookupProcessThreadByCid(IN PCLIENT_ID Cid,
00944                            OUT PEPROCESS *Process OPTIONAL,
00945                            OUT PETHREAD *Thread)
00946 {
00947     PHANDLE_TABLE_ENTRY CidEntry;
00948     PETHREAD FoundThread;
00949     NTSTATUS Status = STATUS_INVALID_CID;
00950     PAGED_CODE();
00951     PSTRACE(PS_PROCESS_DEBUG, "Cid: %p\n", Cid);
00952     KeEnterCriticalRegion();
00953 
00954     /* Get the CID Handle Entry */
00955     CidEntry = ExMapHandleToPointer(PspCidTable, Cid->UniqueThread);
00956     if (CidEntry)
00957     {
00958         /* Get the Process */
00959         FoundThread = CidEntry->Object;
00960 
00961         /* Make sure it's really a thread and this process' */
00962         if ((FoundThread->Tcb.Header.Type == ThreadObject) &&
00963             (FoundThread->Cid.UniqueProcess == Cid->UniqueProcess))
00964         {
00965             /* Safe Reference and return it */
00966             if (ObReferenceObjectSafe(FoundThread))
00967             {
00968                 *Thread = FoundThread;
00969                 Status = STATUS_SUCCESS;
00970 
00971                 /* Check if we should return the Process too */
00972                 if (Process)
00973                 {
00974                     /* Return it and reference it */
00975                     *Process = FoundThread->ThreadsProcess;
00976                     ObReferenceObject(*Process);
00977                 }
00978             }
00979         }
00980 
00981         /* Unlock the Entry */
00982         ExUnlockHandleTableEntry(PspCidTable, CidEntry);
00983     }
00984 
00985     /* Return to caller */
00986     KeLeaveCriticalRegion();
00987     return Status;
00988 }
00989 
00990 /*
00991  * @implemented
00992  */
00993 LARGE_INTEGER
00994 NTAPI
00995 PsGetProcessExitTime(VOID)
00996 {
00997     return PsGetCurrentProcess()->ExitTime;
00998 }
00999 
01000 /*
01001  * @implemented
01002  */
01003 LONGLONG
01004 NTAPI
01005 PsGetProcessCreateTimeQuadPart(PEPROCESS Process)
01006 {
01007     return Process->CreateTime.QuadPart;
01008 }
01009 
01010 /*
01011  * @implemented
01012  */
01013 PVOID
01014 NTAPI
01015 PsGetProcessDebugPort(PEPROCESS Process)
01016 {
01017     return Process->DebugPort;
01018 }
01019 
01020 /*
01021  * @implemented
01022  */
01023 BOOLEAN
01024 NTAPI
01025 PsGetProcessExitProcessCalled(PEPROCESS Process)
01026 {
01027     return (BOOLEAN)Process->ProcessExiting;
01028 }
01029 
01030 /*
01031  * @implemented
01032  */
01033 NTSTATUS
01034 NTAPI
01035 PsGetProcessExitStatus(PEPROCESS Process)
01036 {
01037     return Process->ExitStatus;
01038 }
01039 
01040 /*
01041  * @implemented
01042  */
01043 HANDLE
01044 NTAPI
01045 PsGetProcessId(PEPROCESS Process)
01046 {
01047     return (HANDLE)Process->UniqueProcessId;
01048 }
01049 
01050 /*
01051  * @implemented
01052  */
01053 LPSTR
01054 NTAPI
01055 PsGetProcessImageFileName(PEPROCESS Process)
01056 {
01057     return (LPSTR)Process->ImageFileName;
01058 }
01059 
01060 /*
01061  * @implemented
01062  */
01063 HANDLE
01064 NTAPI
01065 PsGetProcessInheritedFromUniqueProcessId(PEPROCESS Process)
01066 {
01067     return Process->InheritedFromUniqueProcessId;
01068 }
01069 
01070 /*
01071  * @implemented
01072  */
01073 PEJOB
01074 NTAPI
01075 PsGetProcessJob(PEPROCESS Process)
01076 {
01077     return Process->Job;
01078 }
01079 
01080 /*
01081  * @implemented
01082  */
01083 PPEB
01084 NTAPI
01085 PsGetProcessPeb(PEPROCESS Process)
01086 {
01087     return Process->Peb;
01088 }
01089 
01090 /*
01091  * @implemented
01092  */
01093 ULONG
01094 NTAPI
01095 PsGetProcessPriorityClass(PEPROCESS Process)
01096 {
01097     return Process->PriorityClass;
01098 }
01099 
01100 /*
01101  * @implemented
01102  */
01103 HANDLE
01104 NTAPI
01105 PsGetCurrentProcessId(VOID)
01106 {
01107     return (HANDLE)PsGetCurrentProcess()->UniqueProcessId;
01108 }
01109 
01110 /*
01111  * @implemented
01112  */
01113 ULONG
01114 NTAPI
01115 PsGetCurrentProcessSessionId(VOID)
01116 {
01117     // FIXME: this is broken!
01118     return PtrToUlong(PsGetCurrentProcess()->Session);
01119 }
01120 
01121 /*
01122  * @implemented
01123  */
01124 PVOID
01125 NTAPI
01126 PsGetProcessSectionBaseAddress(PEPROCESS Process)
01127 {
01128     return Process->SectionBaseAddress;
01129 }
01130 
01131 /*
01132  * @implemented
01133  */
01134 PVOID
01135 NTAPI
01136 PsGetProcessSecurityPort(PEPROCESS Process)
01137 {
01138     return Process->SecurityPort;
01139 }
01140 
01141 /*
01142  * @implemented
01143  */
01144 HANDLE
01145 NTAPI
01146 PsGetProcessSessionId(PEPROCESS Process)
01147 {
01148     return (HANDLE)Process->Session;
01149 }
01150 
01151 /*
01152  * @implemented
01153  */
01154 PVOID
01155 NTAPI
01156 PsGetCurrentProcessWin32Process(VOID)
01157 {
01158     return PsGetCurrentProcess()->Win32Process;
01159 }
01160 
01161 /*
01162  * @implemented
01163  */
01164 PVOID
01165 NTAPI
01166 PsGetProcessWin32Process(PEPROCESS Process)
01167 {
01168     return Process->Win32Process;
01169 }
01170 
01171 /*
01172  * @implemented
01173  */
01174 PVOID
01175 NTAPI
01176 PsGetProcessWin32WindowStation(PEPROCESS Process)
01177 {
01178     return Process->Win32WindowStation;
01179 }
01180 
01181 /*
01182  * @implemented
01183  */
01184 BOOLEAN
01185 NTAPI
01186 PsIsProcessBeingDebugged(PEPROCESS Process)
01187 {
01188     return Process->DebugPort != NULL;
01189 }
01190 
01191 /*
01192  * @implemented
01193  */
01194 BOOLEAN
01195 NTAPI
01196 PsIsSystemProcess(IN PEPROCESS Process)
01197 {
01198     /* Return if this is the System Process */
01199     return Process == PsInitialSystemProcess;
01200 }
01201 
01202 /*
01203  * @implemented
01204  */
01205 VOID
01206 NTAPI
01207 PsSetProcessPriorityClass(PEPROCESS Process,
01208                           ULONG PriorityClass)
01209 {
01210     Process->PriorityClass = (UCHAR)PriorityClass;
01211 }
01212 
01213 /*
01214  * @implemented
01215  */
01216 VOID
01217 NTAPI
01218 PsSetProcessSecurityPort(PEPROCESS Process,
01219                          PVOID SecurityPort)
01220 {
01221     Process->SecurityPort = SecurityPort;
01222 }
01223 
01224 /*
01225  * @implemented
01226  */
01227 VOID
01228 NTAPI
01229 PsSetProcessWin32Process(PEPROCESS Process,
01230                          PVOID Win32Process)
01231 {
01232     Process->Win32Process = Win32Process;
01233 }
01234 
01235 /*
01236  * @implemented
01237  */
01238 VOID
01239 NTAPI
01240 PsSetProcessWindowStation(PEPROCESS Process,
01241                           PVOID WindowStation)
01242 {
01243     Process->Win32WindowStation = WindowStation;
01244 }
01245 
01246 /*
01247  * @implemented
01248  */
01249 VOID
01250 NTAPI
01251 PsSetProcessPriorityByClass(IN PEPROCESS Process,
01252                             IN PSPROCESSPRIORITYMODE Type)
01253 {
01254     UCHAR Quantum;
01255     ULONG Priority;
01256     PSTRACE(PS_PROCESS_DEBUG, "Process: %p Type: %lx\n", Process, Type);
01257 
01258     /* Compute quantum and priority */
01259     Priority = PspComputeQuantumAndPriority(Process, Type, &Quantum);
01260 
01261     /* Set them */
01262     KeSetPriorityAndQuantumProcess(&Process->Pcb, Priority, Quantum);
01263 }
01264 
01265 /*
01266  * @implemented
01267  */
01268 NTSTATUS
01269 NTAPI
01270 NtCreateProcessEx(OUT PHANDLE ProcessHandle,
01271                   IN ACCESS_MASK DesiredAccess,
01272                   IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
01273                   IN HANDLE ParentProcess,
01274                   IN ULONG Flags,
01275                   IN HANDLE SectionHandle OPTIONAL,
01276                   IN HANDLE DebugPort OPTIONAL,
01277                   IN HANDLE ExceptionPort OPTIONAL,
01278                   IN BOOLEAN InJob)
01279 {
01280     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
01281     NTSTATUS Status;
01282     PAGED_CODE();
01283     PSTRACE(PS_PROCESS_DEBUG,
01284             "ParentProcess: %p Flags: %lx\n", ParentProcess, Flags);
01285 
01286     /* Check if we came from user mode */
01287     if (PreviousMode != KernelMode)
01288     {
01289         _SEH2_TRY
01290         {
01291             /* Probe process handle */
01292             ProbeForWriteHandle(ProcessHandle);
01293         }
01294         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
01295         {
01296             /* Return the exception code */
01297             _SEH2_YIELD(return _SEH2_GetExceptionCode());
01298         }
01299         _SEH2_END;
01300     }
01301 
01302     /* Make sure there's a parent process */
01303     if (!ParentProcess)
01304     {
01305         /* Can't create System Processes like this */
01306         Status = STATUS_INVALID_PARAMETER;
01307     }
01308     else
01309     {
01310         /* Create a user Process */
01311         Status = PspCreateProcess(ProcessHandle,
01312                                   DesiredAccess,
01313                                   ObjectAttributes,
01314                                   ParentProcess,
01315                                   Flags,
01316                                   SectionHandle,
01317                                   DebugPort,
01318                                   ExceptionPort,
01319                                   InJob);
01320     }
01321 
01322     /* Return Status */
01323     return Status;
01324 }
01325 
01326 /*
01327  * @implemented
01328  */
01329 NTSTATUS
01330 NTAPI
01331 NtCreateProcess(OUT PHANDLE ProcessHandle,
01332                 IN ACCESS_MASK DesiredAccess,
01333                 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
01334                 IN HANDLE ParentProcess,
01335                 IN BOOLEAN InheritObjectTable,
01336                 IN HANDLE SectionHandle OPTIONAL,
01337                 IN HANDLE DebugPort OPTIONAL,
01338                 IN HANDLE ExceptionPort OPTIONAL)
01339 {
01340     ULONG Flags = 0;
01341     PSTRACE(PS_PROCESS_DEBUG,
01342             "Parent: %p Attributes: %p\n", ParentProcess, ObjectAttributes);
01343 
01344     /* Set new-style flags */
01345     if ((ULONG)SectionHandle & 1) Flags = PS_REQUEST_BREAKAWAY;
01346     if ((ULONG)DebugPort & 1) Flags |= PS_NO_DEBUG_INHERIT;
01347     if (InheritObjectTable) Flags |= PS_INHERIT_HANDLES;
01348 
01349     /* Call the new API */
01350     return NtCreateProcessEx(ProcessHandle,
01351                              DesiredAccess,
01352                              ObjectAttributes,
01353                              ParentProcess,
01354                              Flags,
01355                              SectionHandle,
01356                              DebugPort,
01357                              ExceptionPort,
01358                              FALSE);
01359 }
01360 
01361 /*
01362  * @implemented
01363  */
01364 NTSTATUS
01365 NTAPI
01366 NtOpenProcess(OUT PHANDLE ProcessHandle,
01367               IN ACCESS_MASK DesiredAccess,
01368               IN POBJECT_ATTRIBUTES ObjectAttributes,
01369               IN PCLIENT_ID ClientId)
01370 {
01371     KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
01372     CLIENT_ID SafeClientId;
01373     ULONG Attributes = 0;
01374     HANDLE hProcess;
01375     BOOLEAN HasObjectName = FALSE;
01376     PETHREAD Thread = NULL;
01377     PEPROCESS Process = NULL;
01378     NTSTATUS Status;
01379     ACCESS_STATE AccessState;
01380     AUX_ACCESS_DATA AuxData;
01381     PAGED_CODE();
01382     PSTRACE(PS_PROCESS_DEBUG,
01383             "ClientId: %p Attributes: %p\n", ClientId, ObjectAttributes);
01384 
01385     /* Check if we were called from user mode */
01386     if (PreviousMode != KernelMode)
01387     {
01388         /* Enter SEH for probing */
01389         _SEH2_TRY
01390         {
01391             /* Probe the thread handle */
01392             ProbeForWriteHandle(ProcessHandle);
01393 
01394             /* Check for a CID structure */
01395             if (ClientId)
01396             {
01397                 /* Probe and capture it */
01398                 ProbeForRead(ClientId, sizeof(CLIENT_ID), sizeof(ULONG));
01399                 SafeClientId = *ClientId;
01400                 ClientId = &SafeClientId;
01401             }
01402 
01403             /*
01404              * Just probe the object attributes structure, don't capture it
01405              * completely. This is done later if necessary
01406              */
01407             ProbeForRead(ObjectAttributes,
01408                          sizeof(OBJECT_ATTRIBUTES),
01409                          sizeof(ULONG));
01410             HasObjectName = (ObjectAttributes->ObjectName != NULL);
01411             Attributes = ObjectAttributes->Attributes;
01412         }
01413         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
01414         {
01415             /* Return the exception code */
01416             _SEH2_YIELD(return _SEH2_GetExceptionCode());
01417         }
01418         _SEH2_END;
01419     }
01420     else
01421     {
01422         /* Otherwise just get the data directly */
01423         HasObjectName = (ObjectAttributes->ObjectName != NULL);
01424         Attributes = ObjectAttributes->Attributes;
01425     }
01426 
01427     /* Can't pass both, fail */
01428     if ((HasObjectName) && (ClientId)) return STATUS_INVALID_PARAMETER_MIX;
01429 
01430     /* Create an access state */
01431     Status = SeCreateAccessState(&AccessState,
01432                                  &AuxData,
01433                                  DesiredAccess,
01434                                  &PsProcessType->TypeInfo.GenericMapping);
01435     if (!NT_SUCCESS(Status)) return Status;
01436 
01437     /* Check if this is a debugger */
01438     if (SeSinglePrivilegeCheck(SeDebugPrivilege, PreviousMode))
01439     {
01440         /* Did he want full access? */
01441         if (AccessState.RemainingDesiredAccess & MAXIMUM_ALLOWED)
01442         {
01443             /* Give it to him */
01444             AccessState.PreviouslyGrantedAccess |= PROCESS_ALL_ACCESS;
01445         }
01446         else
01447         {
01448             /* Otherwise just give every other access he could want */
01449             AccessState.PreviouslyGrantedAccess |=
01450                 AccessState.RemainingDesiredAccess;
01451         }
01452 
01453         /* The caller desires nothing else now */
01454         AccessState.RemainingDesiredAccess = 0;
01455     }
01456 
01457     /* Open by name if one was given */
01458     if (HasObjectName)
01459     {
01460         /* Open it */
01461         Status = ObOpenObjectByName(ObjectAttributes,
01462                                     PsProcessType,
01463                                     PreviousMode,
01464                                     &AccessState,
01465                                     0,
01466                                     NULL,
01467                                     &hProcess);
01468 
01469         /* Get rid of the access state */
01470         SeDeleteAccessState(&AccessState);
01471     }
01472     else if (ClientId)
01473     {
01474         /* Open by Thread ID */
01475         if (ClientId->UniqueThread)
01476         {
01477             /* Get the Process */
01478             Status = PsLookupProcessThreadByCid(ClientId, &Process, &Thread);
01479         }
01480         else
01481         {
01482             /* Get the Process */
01483             Status = PsLookupProcessByProcessId(ClientId->UniqueProcess,
01484                                                 &Process);
01485         }
01486 
01487         /* Check if we didn't find anything */
01488         if (!NT_SUCCESS(Status))
01489         {
01490             /* Get rid of the access state and return */
01491             SeDeleteAccessState(&AccessState);
01492             return Status;
01493         }
01494 
01495         /* Open the Process Object */
01496         Status = ObOpenObjectByPointer(Process,
01497                                        Attributes,
01498                                        &AccessState,
01499                                        0,
01500                                        PsProcessType,
01501                                        PreviousMode,
01502                                        &hProcess);
01503 
01504         /* Delete the access state */
01505         SeDeleteAccessState(&AccessState);
01506 
01507         /* Dereference the thread if we used it */
01508         if (Thread) ObDereferenceObject(Thread);
01509 
01510         /* Dereference the Process */
01511         ObDereferenceObject(Process);
01512     }
01513     else
01514     {
01515         /* neither an object name nor a client id was passed */
01516         return STATUS_INVALID_PARAMETER_MIX;
01517     }
01518 
01519     /* Check for success */
01520     if (NT_SUCCESS(Status))
01521     {
01522         /* Use SEH for write back */
01523         _SEH2_TRY
01524         {
01525             /* Write back the handle */
01526             *ProcessHandle = hProcess;
01527         }
01528         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
01529         {
01530             /* Get the exception code */
01531             Status = _SEH2_GetExceptionCode();
01532         }
01533         _SEH2_END;
01534     }
01535 
01536     /* Return status */
01537     return Status;
01538 }
01539 /* EOF */

Generated on Fri May 25 2012 04:15:31 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.