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