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

Information | Donate

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

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

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

ReactOS Development > Doxygen

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

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