Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenprocsup.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS CSR Sub System 00004 * FILE: subsystems/win32/csrss/csrsrv/procsup.c 00005 * PURPOSE: CSR Process Management 00006 * PROGRAMMERS: ReactOS Portable Systems Group 00007 * Alex Ionescu 00008 */ 00009 00010 /* INCLUDES *******************************************************************/ 00011 00012 #include <srv.h> 00013 00014 #define NDEBUG 00015 #include <debug.h> 00016 00017 /* GLOBALS ********************************************************************/ 00018 00019 RTL_CRITICAL_SECTION ProcessDataLock; 00020 PCSR_PROCESS CsrRootProcess; 00021 SECURITY_QUALITY_OF_SERVICE CsrSecurityQos = 00022 { 00023 sizeof(SECURITY_QUALITY_OF_SERVICE), 00024 SecurityImpersonation, 00025 SECURITY_STATIC_TRACKING, 00026 FALSE 00027 }; 00028 LONG CsrProcessSequenceCount = 5; 00029 extern ULONG CsrTotalPerProcessDataLength; 00030 00031 /* FUNCTIONS ******************************************************************/ 00032 00033 VOID 00034 NTAPI 00035 CsrSetToNormalPriority(VOID) 00036 { 00037 KPRIORITY BasePriority = (8 + 1) + 4; 00038 00039 /* Set the Priority */ 00040 NtSetInformationProcess(NtCurrentProcess(), 00041 ProcessBasePriority, 00042 &BasePriority, 00043 sizeof(KPRIORITY)); 00044 } 00045 00046 VOID 00047 NTAPI 00048 CsrSetToShutdownPriority(VOID) 00049 { 00050 KPRIORITY SetBasePriority = (8 + 1) + 6; 00051 BOOLEAN Old; 00052 00053 /* Get the shutdown privilege */ 00054 if (NT_SUCCESS(RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, 00055 TRUE, 00056 FALSE, 00057 &Old))) 00058 { 00059 /* Set the Priority */ 00060 NtSetInformationProcess(NtCurrentProcess(), 00061 ProcessBasePriority, 00062 &SetBasePriority, 00063 sizeof(KPRIORITY)); 00064 } 00065 } 00066 00067 NTSTATUS 00068 NTAPI 00069 CsrGetProcessLuid(HANDLE hProcess OPTIONAL, 00070 PLUID Luid) 00071 { 00072 HANDLE hToken = NULL; 00073 NTSTATUS Status; 00074 ULONG Length; 00075 PTOKEN_STATISTICS TokenStats; 00076 00077 /* Check if we have a handle to a CSR Process */ 00078 if (!hProcess) 00079 { 00080 /* We don't, so try opening the Thread's Token */ 00081 Status = NtOpenThreadToken(NtCurrentThread(), 00082 TOKEN_QUERY, 00083 FALSE, 00084 &hToken); 00085 00086 /* Check for success */ 00087 if (!NT_SUCCESS(Status)) 00088 { 00089 /* If we got some other failure, then return and quit */ 00090 if (Status != STATUS_NO_TOKEN) return Status; 00091 00092 /* We don't have a Thread Token, use a Process Token */ 00093 hProcess = NtCurrentProcess(); 00094 hToken = NULL; 00095 } 00096 } 00097 00098 /* Check if we have a token by now */ 00099 if (!hToken) 00100 { 00101 /* No token yet, so open the Process Token */ 00102 Status = NtOpenProcessToken(hProcess, 00103 TOKEN_QUERY, 00104 &hToken); 00105 if (!NT_SUCCESS(Status)) 00106 { 00107 /* Still no token, return the error */ 00108 return Status; 00109 } 00110 } 00111 00112 /* Now get the size we'll need for the Token Information */ 00113 Status = NtQueryInformationToken(hToken, 00114 TokenStatistics, 00115 NULL, 00116 0, 00117 &Length); 00118 00119 /* Allocate memory for the Token Info */ 00120 if (!(TokenStats = RtlAllocateHeap(CsrHeap, 0, Length))) 00121 { 00122 /* Fail and close the token */ 00123 NtClose(hToken); 00124 return STATUS_NO_MEMORY; 00125 } 00126 00127 /* Now query the information */ 00128 Status = NtQueryInformationToken(hToken, 00129 TokenStatistics, 00130 TokenStats, 00131 Length, 00132 &Length); 00133 00134 /* Close the handle */ 00135 NtClose(hToken); 00136 00137 /* Check for success */ 00138 if (NT_SUCCESS(Status)) 00139 { 00140 /* Return the LUID */ 00141 *Luid = TokenStats->AuthenticationId; 00142 } 00143 00144 /* Free the query information */ 00145 RtlFreeHeap(CsrHeap, 0, TokenStats); 00146 00147 /* Return the Status */ 00148 return Status; 00149 } 00150 00151 BOOLEAN 00152 NTAPI 00153 CsrImpersonateClient(IN PCSR_THREAD CsrThread) 00154 { 00155 NTSTATUS Status; 00156 PCSR_THREAD CurrentThread = NtCurrentTeb()->CsrClientThread; 00157 00158 /* Use the current thread if none given */ 00159 if (!CsrThread) CsrThread = CurrentThread; 00160 00161 /* Still no thread, something is wrong */ 00162 if (!CsrThread) 00163 { 00164 /* Failure */ 00165 return FALSE; 00166 } 00167 00168 /* Make the call */ 00169 Status = NtImpersonateThread(NtCurrentThread(), 00170 CsrThread->ThreadHandle, 00171 &CsrSecurityQos); 00172 00173 if (!NT_SUCCESS(Status)) 00174 { 00175 /* Failure */ 00176 return FALSE; 00177 } 00178 00179 /* Increase the impersonation count for the current thread */ 00180 if (CurrentThread) ++CurrentThread->ImpersonationCount; 00181 00182 /* Return Success */ 00183 return TRUE; 00184 } 00185 00186 BOOLEAN 00187 NTAPI 00188 CsrRevertToSelf(VOID) 00189 { 00190 NTSTATUS Status; 00191 PCSR_THREAD CurrentThread = NtCurrentTeb()->CsrClientThread; 00192 HANDLE ImpersonationToken = NULL; 00193 00194 /* Check if we have a Current Thread */ 00195 if (CurrentThread) 00196 { 00197 /* Make sure impersonation is on */ 00198 if (!CurrentThread->ImpersonationCount) 00199 { 00200 return FALSE; 00201 } 00202 else if (--CurrentThread->ImpersonationCount > 0) 00203 { 00204 /* Success; impersonation count decreased but still not zero */ 00205 return TRUE; 00206 } 00207 } 00208 00209 /* Impersonation has been totally removed, revert to ourselves */ 00210 Status = NtSetInformationThread(NtCurrentThread(), 00211 ThreadImpersonationToken, 00212 &ImpersonationToken, 00213 sizeof(HANDLE)); 00214 00215 /* Return TRUE or FALSE */ 00216 return NT_SUCCESS(Status); 00217 } 00218 00219 PCSR_PROCESS 00220 NTAPI 00221 FindProcessForShutdown(IN PLUID CallerLuid) 00222 { 00223 PCSR_PROCESS CsrProcess, ReturnCsrProcess = NULL; 00224 NTSTATUS Status; 00225 ULONG Level = 0; 00226 LUID ProcessLuid; 00227 LUID SystemLuid = SYSTEM_LUID; 00228 BOOLEAN IsSystemLuid = FALSE, IsOurLuid = FALSE; 00229 PLIST_ENTRY NextEntry; 00230 00231 /* Set the List Pointers */ 00232 NextEntry = CsrRootProcess->ListLink.Flink; 00233 while (NextEntry != &CsrRootProcess->ListLink) 00234 { 00235 /* Get the process */ 00236 CsrProcess = CONTAINING_RECORD(NextEntry, CSR_PROCESS, ListLink); 00237 00238 /* Move to the next entry */ 00239 NextEntry = NextEntry->Flink; 00240 00241 /* Skip this process if it's already been processed */ 00242 if (CsrProcess->Flags & CsrProcessSkipShutdown) continue; 00243 00244 /* Get the LUID of this Process */ 00245 Status = CsrGetProcessLuid(CsrProcess->ProcessHandle, &ProcessLuid); 00246 00247 /* Check if we didn't get access to the LUID */ 00248 if (Status == STATUS_ACCESS_DENIED) 00249 { 00250 /* FIXME:Check if we have any threads */ 00251 } 00252 00253 if (!NT_SUCCESS(Status)) 00254 { 00255 /* We didn't have access, so skip it */ 00256 CsrProcess->Flags |= CsrProcessSkipShutdown; 00257 continue; 00258 } 00259 00260 /* Check if this is the System LUID */ 00261 if ((IsSystemLuid = RtlEqualLuid(&ProcessLuid, &SystemLuid))) 00262 { 00263 /* Mark this process */ 00264 CsrProcess->ShutdownFlags |= CsrShutdownSystem; 00265 } 00266 else if (!(IsOurLuid = RtlEqualLuid(&ProcessLuid, CallerLuid))) 00267 { 00268 /* Our LUID doesn't match with the caller's */ 00269 CsrProcess->ShutdownFlags |= CsrShutdownOther; 00270 } 00271 00272 /* Check if we're past the previous level */ 00273 if (CsrProcess->ShutdownLevel > Level) 00274 { 00275 /* Update the level */ 00276 Level = CsrProcess->ShutdownLevel; 00277 00278 /* Set the final process */ 00279 ReturnCsrProcess = CsrProcess; 00280 } 00281 } 00282 00283 /* Check if we found a process */ 00284 if (ReturnCsrProcess) 00285 { 00286 /* Skip this one next time */ 00287 ReturnCsrProcess->Flags |= CsrProcessSkipShutdown; 00288 } 00289 00290 return ReturnCsrProcess; 00291 } 00292 00293 /* This is really "CsrShutdownProcess", mostly */ 00294 NTSTATUS 00295 WINAPI 00296 CsrEnumProcesses(IN CSRSS_ENUM_PROCESS_PROC EnumProc, 00297 IN PVOID Context) 00298 { 00299 PVOID* RealContext = (PVOID*)Context; 00300 PLUID CallerLuid = RealContext[0]; 00301 PCSR_PROCESS CsrProcess = NULL; 00302 NTSTATUS Status = STATUS_UNSUCCESSFUL; 00303 BOOLEAN FirstTry; 00304 PLIST_ENTRY NextEntry; 00305 ULONG Result = 0; 00306 00307 /* Acquire process lock */ 00308 CsrAcquireProcessLock(); 00309 00310 /* Get the list pointers */ 00311 NextEntry = CsrRootProcess->ListLink.Flink; 00312 while (NextEntry != &CsrRootProcess->ListLink) 00313 { 00314 /* Get the Process */ 00315 CsrProcess = CONTAINING_RECORD(NextEntry, CSR_PROCESS, ListLink); 00316 00317 /* Remove the skip flag, set shutdown flags to 0*/ 00318 CsrProcess->Flags &= ~CsrProcessSkipShutdown; 00319 CsrProcess->ShutdownFlags = 0; 00320 00321 /* Move to the next */ 00322 NextEntry = NextEntry->Flink; 00323 } 00324 00325 /* Set shudown Priority */ 00326 CsrSetToShutdownPriority(); 00327 00328 /* Loop all processes */ 00329 //DPRINT1("Enumerating for LUID: %lx %lx\n", CallerLuid->HighPart, CallerLuid->LowPart); 00330 00331 /* Start looping */ 00332 while (TRUE) 00333 { 00334 /* Find the next process to shutdown */ 00335 FirstTry = TRUE; 00336 if (!(CsrProcess = FindProcessForShutdown(CallerLuid))) 00337 { 00338 /* Done, quit */ 00339 CsrReleaseProcessLock(); 00340 Status = STATUS_SUCCESS; 00341 goto Quickie; 00342 } 00343 00344 LoopAgain: 00345 /* Release the lock, make the callback, and acquire it back */ 00346 //DPRINT1("Found process: %lx\n", CsrProcess->ClientId.UniqueProcess); 00347 CsrReleaseProcessLock(); 00348 Result = (ULONG)EnumProc(CsrProcess, (PVOID)((ULONG_PTR)Context | FirstTry)); 00349 CsrAcquireProcessLock(); 00350 00351 /* Check the result */ 00352 //DPRINT1("Result: %d\n", Result); 00353 if (Result == CsrShutdownCsrProcess) 00354 { 00355 /* The callback unlocked the process */ 00356 break; 00357 } 00358 else if (Result == CsrShutdownNonCsrProcess) 00359 { 00360 /* A non-CSR process, the callback didn't touch it */ 00361 //continue; 00362 } 00363 else if (Result == CsrShutdownCancelled) 00364 { 00365 /* Shutdown was cancelled, unlock and exit */ 00366 CsrReleaseProcessLock(); 00367 Status = STATUS_CANCELLED; 00368 goto Quickie; 00369 } 00370 00371 /* No matches during the first try, so loop again */ 00372 if (FirstTry && Result == CsrShutdownNonCsrProcess) 00373 { 00374 FirstTry = FALSE; 00375 goto LoopAgain; 00376 } 00377 } 00378 00379 Quickie: 00380 /* Return to normal priority */ 00381 CsrSetToNormalPriority(); 00382 return Status; 00383 } 00384 00385 /*++ 00386 * @name CsrProcessRefcountZero 00387 * 00388 * The CsrProcessRefcountZero routine is executed when a CSR Process has lost 00389 * all its active references. It removes and de-allocates the CSR Process. 00390 * 00391 * @param CsrProcess 00392 * Pointer to the CSR Process that is to be deleted. 00393 * 00394 * @return None. 00395 * 00396 * @remarks Do not call this routine. It is reserved for the internal 00397 * thread management routines when a CSR Process has lost all 00398 * its references. 00399 * 00400 * This routine is called with the Process Lock held. 00401 * 00402 *--*/ 00403 VOID 00404 NTAPI 00405 CsrProcessRefcountZero(IN PCSR_PROCESS CsrProcess) 00406 { 00407 ASSERT(ProcessStructureListLocked()); 00408 00409 /* Remove the Process from the list */ 00410 CsrRemoveProcess(CsrProcess); 00411 00412 /* Check if there's a session */ 00413 if (CsrProcess->NtSession) 00414 { 00415 /* Dereference the Session */ 00416 CsrDereferenceNtSession(CsrProcess->NtSession, 0); 00417 } 00418 00419 /* Close the Client Port if there is one */ 00420 if (CsrProcess->ClientPort) NtClose(CsrProcess->ClientPort); 00421 00422 /* Close the process handle */ 00423 NtClose(CsrProcess->ProcessHandle); 00424 00425 /* Free the Proces Object */ 00426 CsrDeallocateProcess(CsrProcess); 00427 } 00428 00429 /*++ 00430 * @name CsrLockedDereferenceProcess 00431 * 00432 * The CsrLockedDereferenceProcess dereferences a CSR Process while the 00433 * Process Lock is already being held. 00434 * 00435 * @param CsrProcess 00436 * Pointer to the CSR Process to be dereferenced. 00437 * 00438 * @return None. 00439 * 00440 * @remarks This routine will return with the Process Lock held. 00441 * 00442 *--*/ 00443 VOID 00444 NTAPI 00445 CsrLockedDereferenceProcess(PCSR_PROCESS CsrProcess) 00446 { 00447 LONG LockCount; 00448 00449 /* Decrease reference count */ 00450 LockCount = --CsrProcess->ReferenceCount; 00451 ASSERT(LockCount >= 0); 00452 if (!LockCount) 00453 { 00454 /* Call the generic cleanup code */ 00455 DPRINT1("Should kill process: %p\n", CsrProcess); 00456 CsrProcessRefcountZero(CsrProcess); 00457 CsrAcquireProcessLock(); 00458 } 00459 } 00460 00461 /*++ 00462 * @name CsrDereferenceProcess 00463 * @implemented NT4 00464 * 00465 * The CsrDereferenceProcess routine removes a reference from a CSR Process. 00466 * 00467 * @param CsrThread 00468 * Pointer to the CSR Process to dereference. 00469 * 00470 * @return None. 00471 * 00472 * @remarks If the reference count has reached zero (ie: the CSR Process has 00473 * no more active references), it will be deleted. 00474 * 00475 *--*/ 00476 VOID 00477 NTAPI 00478 CsrDereferenceProcess(IN PCSR_PROCESS CsrProcess) 00479 { 00480 LONG LockCount; 00481 00482 /* Acquire process lock */ 00483 CsrAcquireProcessLock(); 00484 00485 /* Decrease reference count */ 00486 LockCount = --CsrProcess->ReferenceCount; 00487 ASSERT(LockCount >= 0); 00488 if (!LockCount) 00489 { 00490 /* Call the generic cleanup code */ 00491 CsrProcessRefcountZero(CsrProcess); 00492 } 00493 else 00494 { 00495 /* Just release the lock */ 00496 CsrReleaseProcessLock(); 00497 } 00498 } 00499 00500 /*++ 00501 * @name CsrDestroyProcess 00502 * @implemented NT4 00503 * 00504 * The CsrDestroyProcess routine destroys the CSR Process corresponding to 00505 * a given Client ID. 00506 * 00507 * @param Cid 00508 * Pointer to the Client ID Structure corresponding to the CSR 00509 * Process which is about to be destroyed. 00510 * 00511 * @param ExitStatus 00512 * Unused. 00513 * 00514 * @return STATUS_SUCCESS in case of success, STATUS_THREAD_IS_TERMINATING 00515 * if the CSR Process is already terminating. 00516 * 00517 * @remarks None. 00518 * 00519 *--*/ 00520 NTSTATUS 00521 NTAPI 00522 CsrDestroyProcess(IN PCLIENT_ID Cid, 00523 IN NTSTATUS ExitStatus) 00524 { 00525 PCSR_THREAD CsrThread; 00526 PCSR_PROCESS CsrProcess; 00527 CLIENT_ID ClientId = *Cid; 00528 PLIST_ENTRY NextEntry; 00529 00530 /* Acquire lock */ 00531 CsrAcquireProcessLock(); 00532 00533 /* Find the thread */ 00534 CsrThread = CsrLocateThreadByClientId(&CsrProcess, &ClientId); 00535 00536 /* Make sure we got one back, and that it's not already gone */ 00537 if (!(CsrThread) || (CsrProcess->Flags & CsrProcessTerminating)) 00538 { 00539 /* Release the lock and return failure */ 00540 CsrReleaseProcessLock(); 00541 return STATUS_THREAD_IS_TERMINATING; 00542 } 00543 00544 /* Set the terminated flag */ 00545 CsrProcess->Flags |= CsrProcessTerminating; 00546 00547 /* Get the List Pointers */ 00548 NextEntry = CsrProcess->ThreadList.Flink; 00549 while (NextEntry != &CsrProcess->ThreadList) 00550 { 00551 /* Get the current thread entry */ 00552 CsrThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, Link); 00553 00554 /* Make sure the thread isn't already dead */ 00555 if (CsrThread->Flags & CsrThreadTerminated) 00556 { 00557 NextEntry = NextEntry->Flink; 00558 continue; 00559 } 00560 00561 /* Set the Terminated flag */ 00562 CsrThread->Flags |= CsrThreadTerminated; 00563 00564 /* Acquire the Wait Lock */ 00565 CsrAcquireWaitLock(); 00566 00567 /* Do we have an active wait block? */ 00568 if (CsrThread->WaitBlock) 00569 { 00570 /* Notify waiters of termination */ 00571 CsrNotifyWaitBlock(CsrThread->WaitBlock, 00572 NULL, 00573 NULL, 00574 NULL, 00575 CsrProcessTerminating, 00576 TRUE); 00577 } 00578 00579 /* Release the Wait Lock */ 00580 CsrReleaseWaitLock(); 00581 00582 /* Dereference the thread */ 00583 CsrLockedDereferenceThread(CsrThread); 00584 NextEntry = CsrProcess->ThreadList.Flink; 00585 } 00586 00587 /* Release the Process Lock and return success */ 00588 CsrReleaseProcessLock(); 00589 return STATUS_SUCCESS; 00590 } 00591 00592 /*++ 00593 * @name CsrCreateProcess 00594 * @implemented NT4 00595 * 00596 * Do nothing for 500ms. 00597 * 00598 * @param ArgumentCount 00599 * Description of the parameter. Wrapped to more lines on ~70th 00600 * column. 00601 * 00602 * @param Arguments 00603 * Description of the parameter. Wrapped to more lines on ~70th 00604 * column. 00605 * 00606 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL 00607 * othwerwise. 00608 * 00609 * @remarks None. 00610 * 00611 *--*/ 00612 NTSTATUS 00613 NTAPI 00614 CsrCreateProcess(IN HANDLE hProcess, 00615 IN HANDLE hThread, 00616 IN PCLIENT_ID ClientId, 00617 IN PCSR_NT_SESSION NtSession, 00618 IN ULONG Flags, 00619 IN PCLIENT_ID DebugCid) 00620 { 00621 PCSR_THREAD CurrentThread = NtCurrentTeb()->CsrClientThread; 00622 CLIENT_ID CurrentCid; 00623 PCSR_PROCESS CurrentProcess; 00624 // PVOID ProcessData; 00625 // ULONG i; 00626 PCSR_PROCESS CsrProcess; 00627 NTSTATUS Status; 00628 PCSR_THREAD CsrThread; 00629 KERNEL_USER_TIMES KernelTimes; 00630 00631 /* Get the current CID and lock Processes */ 00632 CurrentCid = CurrentThread->ClientId; 00633 CsrAcquireProcessLock(); 00634 00635 /* Get the current CSR Thread */ 00636 CurrentThread = CsrLocateThreadByClientId(&CurrentProcess, &CurrentCid); 00637 if (!CurrentThread) 00638 { 00639 /* We've failed to locate the thread */ 00640 CsrReleaseProcessLock(); 00641 return STATUS_THREAD_IS_TERMINATING; 00642 } 00643 00644 /* Allocate a new Process Object */ 00645 CsrProcess = CsrAllocateProcess(); 00646 if (!CsrProcess) 00647 { 00648 /* Couldn't allocate Process */ 00649 CsrReleaseProcessLock(); 00650 return STATUS_NO_MEMORY; 00651 } 00652 00653 #if 0 00654 /* Inherit the Process Data */ 00655 CurrentProcess = CurrentThread->Process; 00656 ProcessData = &CurrentProcess->ServerData[CSR_SERVER_DLL_MAX]; 00657 for (i = 0; i < CSR_SERVER_DLL_MAX; i++) 00658 { 00659 /* Check if the DLL is Loaded and has Per Process Data */ 00660 if ((CsrLoadedServerDll[i]) && (CsrLoadedServerDll[i]->SizeOfProcessData)) 00661 { 00662 /* Set the pointer */ 00663 CsrProcess->ServerData[i] = ProcessData; 00664 00665 /* Copy the Data */ 00666 RtlMoveMemory(ProcessData, 00667 CurrentProcess->ServerData[i], 00668 CsrLoadedServerDll[i]->SizeOfProcessData); 00669 00670 /* Update next data pointer */ 00671 ProcessData = (PVOID)((ULONG_PTR)ProcessData + 00672 CsrLoadedServerDll[i]->SizeOfProcessData); 00673 } 00674 else 00675 { 00676 /* No data for this Server */ 00677 CsrProcess->ServerData[i] = NULL; 00678 } 00679 } 00680 #endif 00681 00682 /* Set the Exception port to us */ 00683 Status = NtSetInformationProcess(hProcess, 00684 ProcessExceptionPort, 00685 &CsrApiPort, 00686 sizeof(HANDLE)); 00687 if (!NT_SUCCESS(Status)) 00688 { 00689 /* Failed */ 00690 CsrDeallocateProcess(CsrProcess); 00691 CsrReleaseProcessLock(); 00692 return STATUS_NO_MEMORY; 00693 } 00694 00695 /* If Check if CreateProcess got CREATE_NEW_PROCESS_GROUP */ 00696 if (!(Flags & CsrProcessCreateNewGroup)) 00697 { 00698 /* Create new data */ 00699 CsrProcess->ProcessGroupId = HandleToUlong(ClientId->UniqueProcess); 00700 CsrProcess->ProcessGroupSequence = CsrProcess->SequenceNumber; 00701 } 00702 else 00703 { 00704 /* Copy it from the current process */ 00705 CsrProcess->ProcessGroupId = CurrentProcess->ProcessGroupId; 00706 CsrProcess->ProcessGroupSequence = CurrentProcess->ProcessGroupSequence; 00707 } 00708 00709 /* Check if this is a console process */ 00710 if (Flags & CsrProcessIsConsoleApp) CsrProcess->Flags |= CsrProcessIsConsoleApp; 00711 00712 /* Mask out non-debug flags */ 00713 Flags &= ~(CsrProcessIsConsoleApp | CsrProcessCreateNewGroup | CsrProcessPriorityFlags); 00714 00715 /* Check if every process will be debugged */ 00716 if (!(Flags) && (CurrentProcess->DebugFlags & CsrDebugProcessChildren)) 00717 { 00718 /* Pass it on to the current process */ 00719 CsrProcess->DebugFlags = CsrDebugProcessChildren; 00720 CsrProcess->DebugCid = CurrentProcess->DebugCid; 00721 } 00722 00723 /* Check if Debugging was used on this process */ 00724 if ((Flags & (CsrDebugOnlyThisProcess | CsrDebugProcessChildren)) && (DebugCid)) 00725 { 00726 /* Save the debug flag used */ 00727 CsrProcess->DebugFlags = Flags; 00728 00729 /* Save the CID */ 00730 CsrProcess->DebugCid = *DebugCid; 00731 } 00732 00733 /* Check if we debugging is enabled */ 00734 if (CsrProcess->DebugFlags) 00735 { 00736 /* Set the Debug Port to us */ 00737 Status = NtSetInformationProcess(hProcess, 00738 ProcessDebugPort, 00739 &CsrApiPort, 00740 sizeof(HANDLE)); 00741 ASSERT(NT_SUCCESS(Status)); 00742 if (!NT_SUCCESS(Status)) 00743 { 00744 /* Failed */ 00745 CsrDeallocateProcess(CsrProcess); 00746 CsrReleaseProcessLock(); 00747 return STATUS_NO_MEMORY; 00748 } 00749 } 00750 00751 /* Get the Thread Create Time */ 00752 Status = NtQueryInformationThread(hThread, 00753 ThreadTimes, 00754 (PVOID)&KernelTimes, 00755 sizeof(KernelTimes), 00756 NULL); 00757 if (!NT_SUCCESS(Status)) 00758 { 00759 /* Failed */ 00760 CsrDeallocateProcess(CsrProcess); 00761 CsrReleaseProcessLock(); 00762 return STATUS_NO_MEMORY; 00763 } 00764 00765 /* Allocate a CSR Thread Structure */ 00766 CsrThread = CsrAllocateThread(CsrProcess); 00767 if (!CsrThread) 00768 { 00769 /* Failed */ 00770 CsrDeallocateProcess(CsrProcess); 00771 CsrReleaseProcessLock(); 00772 return STATUS_NO_MEMORY; 00773 } 00774 00775 /* Save the data we have */ 00776 CsrThread->CreateTime = KernelTimes.CreateTime; 00777 CsrThread->ClientId = *ClientId; 00778 CsrThread->ThreadHandle = hThread; 00779 ProtectHandle(hThread); 00780 CsrThread->Flags = 0; 00781 00782 /* Insert the Thread into the Process */ 00783 CsrInsertThread(CsrProcess, CsrThread); 00784 00785 /* Reference the session */ 00786 CsrReferenceNtSession(NtSession); 00787 CsrProcess->NtSession = NtSession; 00788 00789 /* Setup Process Data */ 00790 CsrProcess->ClientId = *ClientId; 00791 CsrProcess->ProcessHandle = hProcess; 00792 CsrProcess->ShutdownLevel = 0x280; 00793 00794 /* Set the Priority to Background */ 00795 CsrSetBackgroundPriority(CsrProcess); 00796 00797 /* Insert the Process */ 00798 CsrInsertProcess(NULL, CurrentProcess, CsrProcess); 00799 00800 /* Release lock and return */ 00801 CsrReleaseProcessLock(); 00802 return Status; 00803 } 00804 00805 /*++ 00806 * @name CsrUnlockProcess 00807 * @implemented NT4 00808 * 00809 * The CsrUnlockProcess undoes a previous CsrLockProcessByClientId operation. 00810 * 00811 * @param CsrProcess 00812 * Pointer to a previously locked CSR Process. 00813 * 00814 * @return STATUS_SUCCESS. 00815 * 00816 * @remarks This routine must be called with the Process Lock held. 00817 * 00818 *--*/ 00819 NTSTATUS 00820 NTAPI 00821 CsrUnlockProcess(IN PCSR_PROCESS CsrProcess) 00822 { 00823 /* Dereference the process */ 00824 CsrLockedDereferenceProcess(CsrProcess); 00825 00826 /* Release the lock and return */ 00827 CsrReleaseProcessLock(); 00828 return STATUS_SUCCESS; 00829 } 00830 00831 /*++ 00832 * @name CsrSetBackgroundPriority 00833 * @implemented NT4 00834 * 00835 * The CsrSetBackgroundPriority routine sets the priority for the given CSR 00836 * Process as a Background priority. 00837 * 00838 * @param CsrProcess 00839 * Pointer to the CSR Process whose priority will be modified. 00840 * 00841 * @return None. 00842 * 00843 * @remarks None. 00844 * 00845 *--*/ 00846 VOID 00847 NTAPI 00848 CsrSetBackgroundPriority(IN PCSR_PROCESS CsrProcess) 00849 { 00850 PROCESS_PRIORITY_CLASS PriorityClass; 00851 00852 /* Set the Foreground bit off */ 00853 PriorityClass.Foreground = FALSE; 00854 00855 /* Set the new Priority */ 00856 NtSetInformationProcess(CsrProcess->ProcessHandle, 00857 ProcessPriorityClass, 00858 &PriorityClass, 00859 sizeof(PriorityClass)); 00860 } 00861 00862 /*++ 00863 * @name CsrAllocateProcess 00864 * @implemented NT4 00865 * 00866 * The CsrAllocateProcess routine allocates a new CSR Process object. 00867 * 00868 * @return Pointer to the newly allocated CSR Process. 00869 * 00870 * @remarks None. 00871 * 00872 *--*/ 00873 PCSR_PROCESS 00874 NTAPI 00875 CsrAllocateProcess(VOID) 00876 { 00877 PCSR_PROCESS CsrProcess; 00878 ULONG TotalSize; 00879 00880 /* Calculate the amount of memory this should take */ 00881 TotalSize = sizeof(CSR_PROCESS) + 00882 (CSR_SERVER_DLL_MAX * sizeof(PVOID)) + 00883 CsrTotalPerProcessDataLength; 00884 00885 /* Allocate a Process */ 00886 CsrProcess = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, TotalSize); 00887 if (!CsrProcess) return NULL; 00888 00889 /* Handle the Sequence Number and protect against overflow */ 00890 CsrProcess->SequenceNumber = CsrProcessSequenceCount++; 00891 if (CsrProcessSequenceCount < 5) CsrProcessSequenceCount = 5; 00892 00893 /* Increase the reference count */ 00894 CsrProcess->ReferenceCount++; 00895 00896 /* Initialize the Thread List */ 00897 InitializeListHead(&CsrProcess->ThreadList); 00898 00899 /* Return the Process */ 00900 return CsrProcess; 00901 } 00902 00903 /*++ 00904 * @name CsrLockedReferenceProcess 00905 * 00906 * The CsrLockedReferenceProcess refences a CSR Process while the 00907 * Process Lock is already being held. 00908 * 00909 * @param CsrProcess 00910 * Pointer to the CSR Process to be referenced. 00911 * 00912 * @return None. 00913 * 00914 * @remarks This routine will return with the Process Lock held. 00915 * 00916 *--*/ 00917 VOID 00918 NTAPI 00919 CsrLockedReferenceProcess(IN PCSR_PROCESS CsrProcess) 00920 { 00921 /* Increment the reference count */ 00922 ++CsrProcess->ReferenceCount; 00923 } 00924 00925 /*++ 00926 * @name CsrServerInitialization 00927 * @implemented NT4 00928 * 00929 * The CsrInitializeProcessStructure routine sets up support for CSR Processes 00930 * and CSR Threads. 00931 * 00932 * @param None. 00933 * 00934 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL 00935 * othwerwise. 00936 * 00937 * @remarks None. 00938 * 00939 *--*/ 00940 NTSTATUS 00941 NTAPI 00942 CsrInitializeProcessStructure(VOID) 00943 { 00944 NTSTATUS Status; 00945 ULONG i; 00946 00947 /* Initialize the Lock */ 00948 Status = RtlInitializeCriticalSection(&ProcessDataLock); 00949 if (!NT_SUCCESS(Status)) return Status; 00950 00951 /* Set up the Root Process */ 00952 CsrRootProcess = CsrAllocateProcess(); 00953 if (!CsrRootProcess) return STATUS_NO_MEMORY; 00954 00955 /* Set up the minimal information for it */ 00956 InitializeListHead(&CsrRootProcess->ListLink); 00957 CsrRootProcess->ProcessHandle = (HANDLE)-1; 00958 CsrRootProcess->ClientId = NtCurrentTeb()->ClientId; 00959 00960 /* Initialize the Thread Hash List */ 00961 for (i = 0; i < 256; i++) InitializeListHead(&CsrThreadHashTable[i]); 00962 00963 /* Initialize the Wait Lock */ 00964 return RtlInitializeCriticalSection(&CsrWaitListsLock); 00965 } 00966 00967 /*++ 00968 * @name CsrDeallocateProcess 00969 * 00970 * The CsrDeallocateProcess frees the memory associated with a CSR Process. 00971 * 00972 * @param CsrProcess 00973 * Pointer to the CSR Process to be freed. 00974 * 00975 * @return None. 00976 * 00977 * @remarks Do not call this routine. It is reserved for the internal 00978 * thread management routines when a CSR Process has been cleanly 00979 * dereferenced and killed. 00980 * 00981 *--*/ 00982 VOID 00983 NTAPI 00984 CsrDeallocateProcess(IN PCSR_PROCESS CsrProcess) 00985 { 00986 /* Free the process object from the heap */ 00987 RtlFreeHeap(CsrHeap, 0, CsrProcess); 00988 } 00989 00990 /*++ 00991 * @name CsrRemoveProcess 00992 * 00993 * The CsrRemoveProcess function undoes a CsrInsertProcess operation and 00994 * removes the CSR Process from the Process List and notifies Server DLLs 00995 * of this removal. 00996 * 00997 * @param CsrProcess 00998 * Pointer to the CSR Process to remove. 00999 * 01000 * @return None. 01001 * 01002 * @remarks None. 01003 * 01004 *--*/ 01005 VOID 01006 NTAPI 01007 CsrRemoveProcess(IN PCSR_PROCESS CsrProcess) 01008 { 01009 PCSR_SERVER_DLL ServerDll; 01010 ULONG i; 01011 ASSERT(ProcessStructureListLocked()); 01012 01013 /* Remove us from the Process List */ 01014 RemoveEntryList(&CsrProcess->ListLink); 01015 01016 /* Release the lock */ 01017 CsrReleaseProcessLock(); 01018 01019 /* Loop every Server DLL */ 01020 for (i = 0; i < CSR_SERVER_DLL_MAX; i++) 01021 { 01022 /* Get the Server DLL */ 01023 ServerDll = CsrLoadedServerDll[i]; 01024 01025 /* Check if it's valid and if it has a Disconnect Callback */ 01026 if ((ServerDll) && (ServerDll->DisconnectCallback)) 01027 { 01028 /* Call it */ 01029 ServerDll->DisconnectCallback(CsrProcess); 01030 } 01031 } 01032 } 01033 01034 /*++ 01035 * @name CsrInsertProcess 01036 * 01037 * The CsrInsertProcess routine inserts a CSR Process into the Process List 01038 * and notifies Server DLLs of the creation of a new CSR Process. 01039 * 01040 * @param Parent 01041 * Optional pointer to the CSR Process creating this CSR Process. 01042 * 01043 * @param CurrentProcess 01044 * Optional pointer to the current CSR Process. 01045 * 01046 * @param CsrProcess 01047 * Pointer to the CSR Process which is to be inserted. 01048 * 01049 * @return None. 01050 * 01051 * @remarks None. 01052 * 01053 *--*/ 01054 VOID 01055 NTAPI 01056 CsrInsertProcess(IN PCSR_PROCESS Parent OPTIONAL, 01057 IN PCSR_PROCESS CurrentProcess OPTIONAL, 01058 IN PCSR_PROCESS CsrProcess) 01059 { 01060 #if 0 01061 PCSR_SERVER_DLL ServerDll; 01062 ULONG i; 01063 #endif 01064 ASSERT(ProcessStructureListLocked()); 01065 01066 /* Set the parent */ 01067 CsrProcess->Parent = Parent; 01068 01069 /* Insert it into the Root List */ 01070 InsertTailList(&CsrRootProcess->ListLink, &CsrProcess->ListLink); 01071 #if 0 01072 /* Notify the Server DLLs */ 01073 for (i = 0; i < CSR_SERVER_DLL_MAX; i++) 01074 { 01075 /* Get the current Server DLL */ 01076 ServerDll = CsrLoadedServerDll[i]; 01077 01078 /* Make sure it's valid and that it has callback */ 01079 if ((ServerDll) && (ServerDll->NewProcessCallback)) 01080 { 01081 ServerDll->NewProcessCallback(CurrentProcess, CsrProcess); 01082 } 01083 } 01084 #endif 01085 } 01086 01087 /*++ 01088 * @name CsrLockProcessByClientId 01089 * @implemented NT4 01090 * 01091 * The CsrLockProcessByClientId routine locks the CSR Process corresponding 01092 * to the given Process ID and optionally returns it. 01093 * 01094 * @param Pid 01095 * Process ID corresponding to the CSR Process which will be locked. 01096 * 01097 * @param CsrProcess 01098 * Optional pointer to a CSR Process pointer which will hold the 01099 * CSR Process corresponding to the given Process ID. 01100 * 01101 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL 01102 * othwerwise. 01103 * 01104 * @remarks Locking a CSR Process is defined as acquiring an extra 01105 * reference to it and returning with the Process Lock held. 01106 * 01107 *--*/ 01108 NTSTATUS 01109 NTAPI 01110 CsrLockProcessByClientId(IN HANDLE Pid, 01111 OUT PCSR_PROCESS *CsrProcess) 01112 { 01113 PLIST_ENTRY NextEntry; 01114 PCSR_PROCESS CurrentProcess = NULL; 01115 NTSTATUS Status; 01116 01117 /* Acquire the lock */ 01118 CsrAcquireProcessLock(); 01119 01120 /* Assume failure */ 01121 ASSERT(CsrProcess != NULL); 01122 *CsrProcess = NULL; 01123 01124 /* Setup the List Pointers */ 01125 NextEntry = &CsrRootProcess->ListLink; 01126 do 01127 { 01128 /* Get the Process */ 01129 CurrentProcess = CONTAINING_RECORD(NextEntry, CSR_PROCESS, ListLink); 01130 01131 /* Check for PID Match */ 01132 if (CurrentProcess->ClientId.UniqueProcess == Pid) 01133 { 01134 Status = STATUS_SUCCESS; 01135 break; 01136 } 01137 01138 /* Next entry */ 01139 NextEntry = NextEntry->Flink; 01140 } while (NextEntry != &CsrRootProcess->ListLink); 01141 01142 /* Check if we didn't find it in the list */ 01143 if (!NT_SUCCESS(Status)) 01144 { 01145 /* Nothing found, release the lock */ 01146 CsrReleaseProcessLock(); 01147 } 01148 else 01149 { 01150 /* Lock the found process and return it */ 01151 CsrLockedReferenceProcess(CurrentProcess); 01152 *CsrProcess = CurrentProcess; 01153 } 01154 01155 /* Return the result */ 01156 return Status; 01157 } 01158 01159 /* EOF */ Generated on Tue May 22 2012 04:41:33 for ReactOS by
1.7.6.1
|