Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenprocess.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
1.7.6.1
|